python调试测试——pytest

pytest

在工程和实践应用中,常常会遇到我们需要进行测试的地方。而pytest是一种非常方便易用的针对小型测试的工具。
详细信息可以参考官方文档

1. 安装

可以直接使用pip安装,输入如下命令:

pip install -U pytest

可以通过如下命令查看对应的版本号:

pytest --version

2 编写一个测试

使用pytest,实质上是搜索目录下对应的文件,并且执行和查看是否出现错误。如下是一个简单的示例:

# content of test_sample.py
def func(x):
    return x + 1
def test_answer():
    assert func(3) == 5 # 该测试会失败,func(3)应该为4

编写该程序后,在该目录下命令行中输入:

pytest ./test_sample.py

然后会检测断言assert的内容的真假,并显示出对应的信息:

========================================== test session starts ========================================== 
platform win32 -- Python 3.7.7, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: C:\Users\dell\Desktop\TEST\py_tmp
collected 1 item

test_sample.py F                                                                                  [100%]

=============================================== FAILURES ================================================
______________________________________________ test_answer ______________________________________________

    def test_answer():
>       assert func(3) == 5 # 该测试会失败,func(3)应该为4
E       assert 4 == 5
E        +  where 4 = func(3)

test_sample.py:5: AssertionError
======================================== short test summary info ======================================== 
FAILED test_sample.py::test_answer - assert 4 == 5
=========================================== 1 failed in 0.04s =========================================== 

其中[100%]指所有测试案例的全部进行了测试。测试完成后,pytest将显示失败报告,因为func(3)并不会返回5而是4。

3. pytest约定

pytest会测试当前目录下所有形如 *_test.pytest_*.py 的文件。
在这些文件中,会执行所有带test前缀的方法或者是函数。其中如果时类方法则需要类以Test开头且没有__init__()方法。

4. 将测试分类

可以使用类来区分不同的测试,例如:

# content of test_class.py
class TestClass:
    def test_one(self):
        x = "this"
        assert "h" in x

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

此时pytest会测试Test类中的两个测试。可以使用命令参数-q(-quite)表示简化输出。该测试将会通过一个失败一个。具体结果为:

pytest -q test_class.py
.F                                                                   [100%]
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________

self = <test_class.TestClass object at 0xdeadbeef>

    def test_two(self):
        x = "hello"
>       assert hasattr(x, "check")
E       AssertionError: assert False
E        +  where False = hasattr('hello', 'check')

test_class.py:8: AssertionError
========================= short test summary info ==========================
FAILED test_class.py::TestClass::test_two - AssertionError: assert False
1 failed, 1 passed in 0.12s

当一个文件中有多个测试类的时候,如下:

# content of test_class2.py
class TestClassOne(object):
    def test_one(self):
        x = "this"
        assert 't'in x

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


class TestClassTwo(object):
    def test_one(self):
        x = "iphone"
        assert 'p'in x

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

可以使用命令指定测试某个类内的测试:
仅执行TestClassOne中的两个测试可以使用命令:

pytest test_class2.py::TestClassOne

仅仅执行TestClassOne中的测试test_one可以使用命令:

pytest test_class2.py::TestClassOne::testone

5. 显示print信息

在进行测试的时候,可能会在代码中添加print语句,产生一些信息。可以使用参数-s来在运行pytest的时候输出这些信息:

pytest test_se.py -s

6. 多进程运行测试

当测试的数目很大的时候,运行时间会比较长。此时可以采用多进程来进行测试。需要先下载安装pytest-xdist

pip install -U pytest-xdist

在使用pytest时,指定参数-n num即可,其中num为进程数:

pytest test_*.py -n num

7. 重试运行测试

有时候可能由于其他原因导致测试失败,需要重试多次运行某个测试。需要下载安装pytest-rerunfailures

pip install -U pytest-rerunfailures

在使用pytest的时候,指定参数--reruns num,其中num为重试次数:

pytest test_*.py -reruns num 

8. 断言

8.1 断言

assert用于判断一个表达式,在表达式条件为 False 的时候触发异常。其语法格式为:

assert Expression

等价于

if not expression:
    raise AssertionError

assert 后面也可以紧跟参数来出发对应的错误类型。同样会在使用pytest中的错误信息中对应地显示出来。

assert expression [, arguments]

8.2 断言几乎相等

在使用断言的时候,浮点数不能直接使用断言来进行判断,其结果一般都会是失败。原因在于浮点数的截断情况导致会比实际值略有一定的偏差。
几种常见的写法是:

assert x - esp <= y <= x + esp		# esp = 1e-6
assert abs(x-y) < esp				# esp = 1e-6

但是对于数组、元组、字典等,需要将数据提取出来在进行比较。实际上我们可以使用pytest.approx来断言几乎相等,示例如下:

assert 2.2 == pytest.approx(2.3)		
# 失败,默认允许2.3e-6的误差
assert 2.2 == pytest.approx(2.3, 0.1)	
# 成功,指定误差是0.1
assert [0.1 + 0.2, 0.2 + 0.4] == pytest.approx([0.3, 0.6])
# 成功,适用于断言一维数组
assert {
    
    'a': 0.1+0.2} == pytest.approx({
    
    'a': 0.3})
# 成功,适用于断言字典
assert [[0.1 + 0.2], [0.2 + 0.4]] == pytest.approx([[0.3], [0.6]])
# 失败,目前pytest不支持多维数组等类型

实际上我们还可以使用numpy.testing来协助比较,详细可以参考它的文档

猜你喜欢

转载自blog.csdn.net/weixin_43762938/article/details/108094778