pytest 官网

https://docs.pytest.org/en/6.2.x/


pytest 的约束


pytest 的运行方式

1,测试类主函数模式

2,命令行模式


pytest 的退出码


pytest 的命令行选项

1,--version

查看版本

2,-s

在测试执行期间,任何标准输出,标准错误输出都会被捕获。如果想禁用该行为,需要设置 --capture=no(-s 是其快捷方式)

3,-r

pytest 单独统计和列出 skip 和 xfail 测试。skipped/xfailed 测试的详细信息不会被展示到输出里。使用 -r 选项可以查看测试过程中的细节。

当 -r 选项被指定为如下字符时,将展示额外的测试信息:

比如:

4,--collect-only

只收集测试用例,不执行

5,--fixtures

显式可用的 fixture,不执行用例

6,--maxfail

在发生 N 次失败或错误后退出。比如:

7,--pyargs

自动导入包,并使用包目录,执行下面的测试用例

8,-n

用多进程运行测试用例。需要安装 xdist 插件:

9,--reruns

重新运行失败的测试用例的次数。需要安装 rerunfailures 插件:

10,--junit-xml

在指定的路径生成 junit-xml 风格的报告文件


pytest 的配置文件

pytest 的配置文件通常放在测试目录下,名字为 pytest.ini,命令行运行时会使用该配置文件中的配置:

更多详情,请参考:https://docs.pytest.org/en/6.2.x/customize.html


pytest 的 setup() 和 teardown() 函数

函数级别

运行于测试方法的始末,即每运行一个测试用例,会运行一次 setup 和 teardown:

类级别

运行于测试类的始末,即在一个测试内只运行一次 setup_class 和 teardown_class,不管类里有多少个测试函数:


pytest 的 test fixture

test fixture 代表执行一个或多个测试用例所需要的准备,以及所有相关的清理操作。比如创建临时的代理数据库、目录,或开启服务进程等。

在 pytest 中,使用 @pytest.fixture 装饰的函数就是一个 fixture。下面是 fixture() 函数的签名:

参数的含义如下:

下面通过一些例子进行说明:

1,通过参数引用

2,通过装饰器引用

3,自动引用

使用如下命令测试 TestFixtureC:

4.1,向 test 传递数据

使用如下命令测试 TestFixtureD:

4.2,使用不同的参数多次调用测试用例


参数化测试

以下内容翻译自:https://docs.pytest.org/en/6.2.x/example/parametrize.html

在 pytest 中可以很容易地参数化测试函数,下面通过一些例子进行说明。

通过命令行生成参数组合

在下面的例子中,通过命令行参数(--all)决定参数的范围,并使用不同的组合参数执行测试:

增加一个类似下面的测试配置:

如果不传递 --all,那么只会执行 2 次测试:

下面传递 --all:

如期望所示,运行了 5 次测试,并且最后一次失败了。

用于 test ID 的选项

在参数化测试中,pytest 将为每个值的集合构建字符串类型的 test ID。这些 ID 可以与 -k 选项一起使用,以选择要运行的用例。test ID 也将标识失败的用例。使用 --collect-only 选项运行 pytest 将展示被生成的 ID。

在 test ID 中,数值、字符串、布尔值和 None 将使用它们的常规字符串形式。对于其它对象而言,pytest 将根据参数名生成字符串:

test_timedistance_v0 中,我们让 pytest 生成 test ID。

test_timedistance_v1 中,我们将 ids 指定为字符串列表。这种方式言简意赅,但是难于维护。

test_timedistance_v2 中,我们将 ids 指定为可以生成字符串形式的函数。因此 datetime 值使用 idfn 生成的标签,但是因为没有为 timedelta 对象生成标签,所以它们仍然使用默认的 pytest 形式:

间接参数化

使用 indirect=True 参数允许使用 fixture 进行参数化测试:

使用多个 fixture 的间接参数化

在下面的例子中,使用参数化测试测试不同 Python 解释器之间的对象序列化。pytest 将使用不同的参数集合调用 test_basic_objects 函数,该函数有三个参数:

如果我们没有安装所有 Python 解释器,那么将导致一些测试被跳过;否则会运行所有的组合(3 个解释器 × 3 个解释器 × 3 个将要序列化/反序列化的对象):

未完待续...


Skip、xfail:处理无法成功的测试

以下内容翻译自:https://docs.pytest.org/en/6.2.x/skipping.html

skip 用于在某些条件满足时,跳过测试。比如在非 windows 平台跳过只能在 windows 平台运行的测试。

xfail 意味着期望测试因某种原因失败。比如测试还没实现的特性,或还没修复的 bug。当被期望失败的测试通过时,它是一个 xpass,并且会被展示在测试摘要中。

跳过测试函数

跳过测试函数最简单的方式是使用 skip 装饰器标记它,skip 接受一个可选的 reason:

另外,也可以在测试执行或设置期间,通过调用 pytest.skip(reason) 函数命令式地跳过测试:

当无法在 import 期间计算跳过条件时,命令式方法非常有用。

也可以在模块级别使用 pytest.skip(reason, allow_module_level=True) 跳过整个模块:

skipif

skipif 可以有条件地跳过测试。在下面的例子中,当在早于 Python3.6 的解释器上运行时,测试函数会被跳过:

如果在收集期间,条件的计算结果为 True,pytest 将跳过测试函数。当使用 -rs 选项时,被指定的原因将出现在测试概要中。

可以在模块间共享 skipif。比如:

可以在其它模块中导入并重用:

另外,也可以使用 condition string 代替 bool 值,但是它们不能方便地在模块间共享,它们被支持的主要原因是为了向后兼容。

跳过类或模块的所有测试方法

可以在类上使用 skipif 标记:

如果条件是 True,那么该类中的所有测试方法都会被跳过。

如果想要跳过一个模块中的所有测试方法,可以使用 pytestmark 全局变量:

当多个 skipif 装饰器被应用到同一个测试函数时,如果任意一个跳过条件为 True,那么该函数将被跳过。

XFail:标记测试函数为预期失败

使用 xfail 标记意味着期望测试失败:

该测试会被运行,但是当它失败时,不会报告 traceback。终端报告会把它列在 XFAIL 或 XPASS 区域。

另外,也可以在测试函数或它的 setup 函数里,命令式地将测试标记为 XFAIL:

注意:pytest.xfail() 调用之后的其它代码不会被执行。

1,condition 参数:

如果测试仅在某个特定条件下,才会被期望为失败,那么可以将该条件作为 xfail 的第一个参数:

注意:此时必须传递 reason 参数。

2,reason 参数:

通过 reason 参数可以指定期望失败的动机:

3,raises 参数:

raise 参数可以是单个异常,也可以是异常元组。当测试函数抛出没在 raises 参数中提及的异常时,它会被报告为常规的失败:

4,run 参数:

如果测试函数被标记为 xfail,并且不想运行它,那么需要将 run 参数设置为 False:

带参数化的 Skip/xfail

当使用参数化时,可以将 skip、xfail 之类的标记应用到独立的用例:

未完待续...


pytest 输出覆盖率报告

1,安装 cov 插件:

2,运行测试用例、统计覆盖率、生成报告: