pytest-知识点

介绍

pytest是python的单元测试框架,类似于python自带的unittest测试框架。
相比unittest使用简洁、效率更高。

pytest和unittest区别

1、pytest是基于unittest衍生出来的新的测试框架,使用起来相对于unittest来说更简单、效率来说更高,pytest兼容unittest测试用例,但是反过来unittest不兼容pytest
2、pytest的断言比unittest要简单些,unittest断言需要记很多断言格式,pytest只有assert一个表达式,用起来比较方便
3、pytest的前置后置比unittest多, 而且可以自定义条件
4、.unittest参数化可以通过nose_parameterized来实现,如@nose_parameterized.parameterized.expand(data),
‘data’为list格式的参数化的数据
而pytest参数化
通过装饰器@pytest.mark.parametrize来实现
5、pytest支持很多插件,比如失败重新执行、控制用例执行顺序、测试报告插件
6、unittest 通过HTMLTestRunner生成测试测试报告
pytest 通过pytest-html生成html格式报告,或者通过allure生成方案

pytest的特点

1、非常容易上手,入门简单,文档丰富,文档中很多实例可以参考
2、支持简单的单元测试和复杂的功能测试
3、支持参数化
4、执行测试过程中可以将某些测试跳过,或者对某些预期失败的case标记为失败
5、支持重复执行失败case
6、支持运行由unittest编写的case
7、具有很多第三方插件,并且可自定义扩展
8、方便和持续集成工具集成

安装

sudo pip install -U pytest
安装成功校验 : pytest --version

获取帮助信息

pytest -h

查看版本信息

pytest --version
在这里插入图片描述

pytest 示例

import pytest

# 不需要创建测试类,直接编写测试函数也ok
# 测试函数名 必须以test开头,或者以test结尾
def test_a():  
    print("aaa")
    assert 1
    
def test_b():
    print('bbb')
    assert 0
    
if __name__ == '__main__':
    pytest.main(['./test.py'])

setup和teardown函数

模块级别,对整个py文件起作用
setup_module / teardown_module
函数级别,对测试用例作用(不在测试类中)
setup_function / teardown_function
类级别,对测试类作用
setup_class/teardown_class
方法级别,对测试类中的测试用例作用(在测试类中)
setup_method / teardown_method

import pytest

def setup_module():
    print("在模块开始执行前执行")

def teardown_module():
    print("在模块运行完后执行")

def setup_function():
    print("在函数执行前执行")

def teardown_function():
    print("在函数执行后执行")

def test_c():
    print("测试用例c")
    assert 1

def test_d():
    print("测试用例d")
    assert 1

class TestCase():
    def setup_class(self):
        print("类开始执行前执行")

    def teardown_class(self):
        print("类执行完后执行")

    def setup_method(self):
        print("类方法开始执行前执行")

    def teardown_method(self):
        print("类方法开始执行前执行")

    def test_e(self):
        print("测试用例e")
        assert 1

    def test_f(self):
        print("测试用例f")
        assert 1

pytest.main(['test_b'])

在这里插入图片描述

测试类

测试类要符合特定的规则,pytest才能发现它:
1、测试类的命令要符合Test*规则;
2、测试类中不能有__init__()方法;
3、测试类中的方法和函数编写规则一致。

class TestClass:
    def test_one(self):
        x = 'this'
        assert 'h' in x

    def test_two(self):
        x = 'hello'
        assert hasattr(x, 'check')

pytest配置文件

pytest的配置文件通常放在测试目录下,名称为pytest.ini,命令运行时会使用配置文件中的配置。注意:pytest.ini文件中不能出现中文。

[pytest]
testpaths = ./  
python_files=test_*.py
python_classes=Test*
python_functions=test_*

运行方式

1、在python代码中调用pytest
pytest.main(["-x", “mytestdir”])

2、执行case-指定模块
$ pytest test.py
在这里插入图片描述
3、 执行case-指定目录
$ pytest testing/

4、 执行case-文件名、类名或者函数名中包含特定关键字
pytest -k “_class and not two” .

5、执行case-指定nodeid
pytest为每一个收集到的测试用例指定一个唯一的nodeid。其由模块名加说明符构成,中间以::间隔。
说明符可以是类名、函数名以及由parametrize标记赋予的参数:
在这里插入图片描述
6、执行case-指定标记
pytest -m slow
7、执行case-指定包
pytest --pyargs pkg.testing
pytest会引入pkg.testing包,并在它的系统目录下搜寻测试用例并执行;

8、 执行多个case
a、执行当前目录及子目录下所有符合test_.py或者_test.py规则的文件。
$ pytest
b、执行指定的测试用例文件
$ pytest test_a.py test_b.py
在这里插入图片描述
9、 通过python -m pytest调用pytest
和pytest 运行效果相同
在这里插入图片描述

执行结束时返回的状态码

pytest命令执行结束,可能会返回以下六种状态码:

0:(OK)所有收集到的用例测试通过
1:(TESTS_FAILED)有用例测试失败
2:(INTERRUPTED)用户打断测试执行
3:(INTERNAL_ERROR)测试执行的过程中,发生内部错误
4:(USAGE_ERROR)pytest命令使用错误
5:(NO_TESTS_COLLECTED)没有收集到测试用例
它们在枚举类 _pytest.main.ExitCode 中声明。并且,其作为公开API的一部分,能够直接引入和访问:
from pytest import ExitCode

pytest 常用插件之控制用例执行顺序

默认情况下测试用例是从上到下执行的。可通过第三方插件改变case执行顺序。
插件名称:pytest-ordering
安装:pip install pytest-ordering
使用:1、在被测试函数上使用 @pytest.mark.run(order=x)
x 越小优先级越高

断点

1、import pdb
import pdb
在需要的地方加入:pdb.set_trace(),当其被调用时,pytest会停止这条用例的输出,其他用例不受影响。通过continue命令,退出PDB环境,并继续执行用例。

2、 使用内置的中断函数 breakpoint()
python 3.7 及以后支持: breakpoint()

3、开始执行时就加载PDB环境
pytest --trace
pytest允许在每个测试用例开始执行时,就加载PDB环境。
在这里插入图片描述
4、失败时加载PDB(Python Debugger)环境
a、PDB是python内建的诊断器,执行pytest --pdb 可进入诊断模式。
b、pytest会在测试用例失败(或者Ctrl+C)时,调用这个诊断器:
c、失败的信息存储在sys.last_value, sys.last_type, sys.last_traceback变量中
d、使用exit命令可退出诊断模式。
在这里插入图片描述

报告

1、总结报告
i、-r选项可以在执行结束后,打印一个简短的总结报告。在执行的测试用例很多时,可以让你对结果有个清晰的了解:
ii、-r选项后面要紧接这一个参数,用于过滤显示测试用例的结果。
以下是所有有效的字符参数:
f:失败的
E:出错的
s:跳过执行的
x:跳过执行,并标记为xfailed的
X:跳过执行,并标记为xpassed的
p:测试通过的
P:测试通过,并且有输出信息的;即用例中有print等
a:除了测试通过的,其他所有的;即除了p和P的
A:所有的
iii、上述字符参数可以叠加使用

2、 创建JUnitXML格式的测试报告
pytest --junitxml=path
可以在指定的path中创建一个能被Jenkins或者其他CI工具读取的XML格式的测试报告

3、 为测试报告提供URL链接 – pastebin服务
a、为每一个失败的测试用例创建一个URL
pytest --pastebin=failed
也可以通过添加-x选项,只为第一个失败的测试用例创建一个URL;

b、为所有的测试用例创建一个URL
pytest --pastebin=all

pytest 常用插件之测试报告

插件名称:pytest-html
安装:pip install pytest-html
使用:在配置文件中添加参数
addopts = --html=report/report.html

设置允许失败的用例数

达到上限后退出循环
pytest -x # 遇到第一个失败时,退出执行
pytest --maxfail==2 # 遇到第二个失败时,退出执行

pytest 常用插件之失败重试

插件名称:pytest-rerunfailures
安装:pip install pytest-rerunfailures
使用:在配置文件命令行添加新参数
失败重跑两次
addopts = --html=report/report.html --reruns=2

修改回溯信息的输出模式

1、pytest回溯信息的输出一共有六种模式:auto/long/short/line/native/no,用–tb选项指定:
pytest -l, --showlocals # 打印本地变量
pytest --tb=auto # 默认模式
pytest --tb=long # 尽可能详细的输出
pytest --tb=short # 更简短的输出
pytest --tb=line # 每个失败信息总结在一行中
pytest --tb=native # python的标准输出
pytest --tb=no # 不打印失败信息
2、–full-trace是一种比–tb=long更详细的输出模式。它甚至能观察到用户打断执行(Ctrl+C)时的回溯信息,而上述六种模式默认是不输出此类信息的。

分析测试执行时间

获取执行最慢的10个测试用例
pytest --durations=10

断言

1、使用python标准的assert表达式写断言
assert a == 0, “value was odd, should be even”

2、 编写触发期望异常的断言

import pytest

def myfunc():
    raise ValueError("Exception 123 raised")

def test_match():
    with pytest.raises(ValueError) as excinfo:
        myfunc()
    assert '123' in str(excinfo.value)

3、 为失败断言添加自定义的说明
a、重写__repr__()方法

class Foo:
    def __init__(self, val):
        self.val = val

    def __repr__(self):
    return str(self.val)
    
def test_foo_compare():
    f1 = Foo(1)
    f2 = Foo(2)
    assert f1 == f2

b、重写pytest_assertrepr_compare()钩子函数

from .test_foo_compare import Foo

def pytest_assertrepr_compare(op, left, right):
    if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
        return [
            "比较两个Foo实例:",  # 顶头写概要
            "   值: {} != {}".format(left.val, right.val),  # 除了第一个行,其余都可以缩进
        ]

跳过测试函数

1、根据特定的条件,不执行标识的测试函数
skipif(condition, reason=None)
condition:跳过的条件,必传参数
reason:标注原因,必传参数
2、在测试用例前使用方法 @pytest.mark.skipif(2>1, reason=“跳过测试”)

标记为预期失败的函数

1、xfail(condition=None, reason=None,raises=None,run=True,strict=False)
condition:预期失败的条件。条件为真时预期失败

2、在测试用例前使用 @pytest.mark.xfail(condition, reason=‘XX’)
3、在配置文件中添加参数
xfail_strict=true ,预测失败但是成功的会算到失败的case里。

函数数据参数化

1、parametrize(argnames, argvalues)
argnames: 参数名
argvalues:参数值,类型列表格式
2、在测试函数前使用@pytest.mark.parametrize(“mobile”,[“13245452452”,“14425625263”])
3、多个参数,注册多个@pytest.mark.parametrize。
或者@pytest.mark.parametrize(“mobile,code”,[(“13245452452”,“120”),(“14425625263”,“121”)])

fixture

1、fixture相对于setup和teardown来说有几个优势
a.命名方式灵活,不局限于setup和teardown这几个命名
b.conftest.py配置里可以实现数据共享,不需要import就能自动找到一些配置。
c.scope = “module” 可以实现多个多个.py跨文件共享前置,每一个.py文件调用一次
d.scope=“session” 可实现多个.py跨文件使用一个session来完成多个用例。
e.fixture(scope=“function”, params=None, autouse=False,ids=None,name=None)
使用装饰器标记fixture功能。
autouse 是否自动启用
2、创建fixture

@pytest.fixture()
# 编写普通函数
def login():
	print("登录获取token")

3、使用fixture
在需要使用fixture的测试用例中,把fixture函数的名词当参数传入即可。

def test_shopping(login):
	print("测试购物")

使用yield 在一个fixture函数中实现teardown

import pytest

@pytest.fixture()
def login():
    print("开始浏览器")
    yield
    print("关闭浏览器")

def test_shop(login):
    print("购物")

if __name__ == '__main__':
    pytest.main(['./test_a.py'])

addfinalizer使用

yield 当用例执行完后 ,会执行yield后面的代码,但是不能return
addfinalizer和yield一样,但是可以return参数,传给后面的测试用例

使用装饰器引用fixture

@pytest.fixture()
def before():
print(“开始执行”)

@pytest.mark.usefixtures(“before”)
def test_a():
pass

pytestconfig

pytestconfig 可以通过命令行参数、选项、配置文件、插件、运行目录等方式来控制pytest;

pytestconfig 实际上就是 request.config 的快捷方式,被称为“pytest 配置对象”;
pytest.config.getoption("–jenkins_job_url") 获取命令行参数
pytestconfig.getini(‘markers’) 获取 pytest.ini 配置文件中参数的值

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值