Skip to content

pytest

提供 用例发现用例筛选用例执行用例报告第三方插件等功能。

官方文档:pytest: helps you write better programs

安装

pip install pytest

使用

使用 pytest 来创建用例、执行用例。

创建用例

  1. 创建 test_ 开头的 .py 文件
  2. 创建 test_ 开头的函数
  3. 在函数中使用 assert 进行断言

pytest 发现测试的规则

  1. 如果未指定 testpaths,则从当前目录开始收集。命令行参数可以用于目录、文件名或节点 ID 的任意组合。
  2. 默认会对目录进行递归查找,除非配置了 norecursedirs
  3. 会发现 test_*.py 或者 *_test.py 命令格式的 python 文件。
  4. 顶层 test 前缀的函数(注意可以不用下划线)。
  5. 没有 __init__ 方法的且以 Test 为前缀的类的 test 前缀的方法。
python

def test_api():
    assert 1 == '1'

执行用例

打开终端,输入:

shell
pytest

或者在 python 文件中执行 pytest.main()

断言方法

assert 表达式

pytest 支持通过 assert 表达式直接进行断言操作,pytest 会对断言进行内省,使得报告信息更加详细。

断言会出现异常

使用 with 语句,执行 pytest.raises 函数:

python
with pytest.raises(预期异常) [as 异常变量]:
    pass # 会抛出异常的语句

配置

pytest 支持使用 -h 参数显示可选的配置项。

也支持使用 pytest.ini 或者 .pytest.ini 进行配置。

配置格式如下:Configuration file formats

ini
addopts = -ra -q

常用选项

  • -v: 增加详细程度
  • -q: 减少冗长
  • -r(chars): 指定要显示的额外测试摘要信息,默认是(fE,失败和错误)
    • f | x:失败
    • E:错误
    • s:跳过的
    • X | p:通过的
    • P:通过的,并输出标准输出内容
    • ap | aP:排除通过的
    • A:全部
  • --no-header: 不显示头部的环境信息
  • --no-summary: 不显示测试结果摘要

fixture(固件)

官方文档:How to use fixtures

fixture 是一种用于在测试函数执行前设置环境或数据的机制。 可以在多个测试之间共享相同的配置或数据,从而避免重复代码并提高测试效率。 fixture 可以是函数、类或者模块级别的,并且可以通过参数化来处理不同的输入情况。 也可以使用 conftest.py 专门存放 fixture

通过使用 @pytest.fixture 装饰器来定义一个 fixture,然后在测试函数中使用 fixture_name 作为参数来访问它。

参数

  • scope:定义固件的作用域(**默认值:function **),官方文档:Fixture Scopes
    • function:函数,所有使用到的测试函数在执行前都会先重新执行一次(包括重试的测试函数)。
    • class:类,在类内部第一个使用到的测试函数执行时会执行一次,其它的不再执行,在类的最后一个用例执行的销毁。
    • module:模块
    • session:会话
  • autouse:是否自动使用(默认值:False),即默认情况下,如果没有使用则不会执行 fixture 函数。
  • name:指定固件的名称(默认值:函数名
  • params:参数化,每一个参数会执行一次,通过 request.param 获取当前的参数值。
  • ids:配合 params 使用,指定 params 的别名。

⚠️ 注意

  • 使用 pytest-rerunfailures 插件时,兼容性较差,scope 配置会失效。
  • 使用 pytest-xdist 插件时,要注意指定合适的方法模式。如使用 loadscope 使得 scope 配置为 class 的 fixture 生效。

pytest 支持 xunit 格式的初始化设置

官方文档:How to implement xunit-style set-up

模块:setup_moduleteardown_module 类:setup_classteardown_class 方法:setup_methodteardown_method 函数:setup_functionteardown_function

添加后置操作

pytest 的 fixture 添加后置操作只需要在函数内部使用一个 yield 关键字即可。

可以使用 yield 关键字代替 return 返回数据。

多个 yield 关键字会报错

fixture function has more than one 'yield'

内置 fixture

官方文档:Built-in fixtures

request

提供有关执行测试功能的信息。

官方文档:reference

tmp_path(临时目录)

为每个测试函数唯一的临时目录提供一个 pathlib.Path 对象。

扩展使用

用例数据分离

插件

官方文档:How to install and use plugins

pytest-html

用于生成 HTML 格式的测试报告。

pypi | Documentation

安装

shell
pip install pytest-html

使用

pytest-html 插件的使用非常简单,只需要配置 --html(生成的 html 存放位置) 选项即可。

配置报告标题

conftest.py 文件中添加:

python
# 在将标题添加到报告之前调用
def pytest_html_report_title(report):
    report.title = "report title"

pytest-rerunfailures

可以重新运行测试以消除间歇性故障。

安装

shell
pip install pytest-rerunfailures

使用

使用 --reruns 直接指定重试次数。

失败的 fixture 或 setup_class 也将被重新执行。

可选配置

  • --reruns-delay:配置每次重试的时间间隔(单位为秒),默认是立即执行
  • --only-rerun:配置要进行重试的错误,可多次传递,eg: --only-rerun=AssertionError --only-return=ValueError
  • --rerun-except:配置只有出现的错误不是提供的错误的才会重试(也支持多次传递),可以通过 assert 表示 AssertionError

针对单个用例配置

可在测试用例上添加 @pytest.mark.flaky

支持 rerunsreruns_delayonly_rerunrerun_expectcondition 参数。

eg:

  • reruns=5:最多重试 5 次。
  • reruns_delay=1:间隔 1 秒一次。
  • rerun_except=AssertionError:只有不是 AssertionError 错误才会重试。
  • only_rerun=["AssertionError", "ValueError"]:只有 AssertionErrorValueError 错误才会重试。
  • condition="sys.platform.startswith('win32')"condition=sys.platform.startswith("win32"):只有 win32 平台才重试。

⚠️ 注意

  • 注意默认情况下 pytest 是一个个测试用例执行的,一个用例重试完成后才会执行执行其它测试用例。 可考虑使用下面的 pytest-xdist 插件。
  • 🧰 rerunfailures 插件和 fixture 不兼容!!!

pytest-xdist

pytest-xdist 插件使用新的测试执行模式扩展了 pytest,最常用的是将测试分布在多个 CPU 上以加速测试执行。

pypi | Documentation

安装

shell
pip install pytest-xdist

使用

使用 -n 直接指定使用的线程数,还支持支持 autological

  • auto:尝试检测物理 CPU 计数。如果无法确定物理 CPU 计数,则回退到 1。
  • logical:尝试检测逻辑 CPU 计数(需要 psutil,否则回退到使用 auto)。

分发方式

通过 --dist 选项指定分发方式。

  • load:默认分发方式,将待处理的测试发送给任何可用的 worker,不保证任何顺序。 可配合(--maxschedchunk) 选项使用,指定每一次提交到 worker 的测试用例数,默认没有限制。
  • loadscope:按模块和类进行分发,类分发优先级高于模块。
  • loadfile:按文件进行分发。
  • loadgroup:通过 @pytest.mark.xdist_group(name="group_name") 指定分组进行分发。
  • worksteal:和 load 类似,分发方式为先平均分配,当一个 worker 执行完成所有的用例后,去窃取其它剩余用例大于 2 的 worker 的用例。
  • no:正常的 pytest 模式,不进行分发。

在多个进程中共享数据

官方文档:Making session-scoped fixtures execute only once

python

allure-pytest

创建精美而清晰的测试报告。

pypi | Documentation

安装

下载对应环境的 allure 安装包。 下载地址

shell
pip install allure-pytest

使用

pytest-html 插件的使用非常简单,只需要配置 --alluredir(生成的报告存放目录) 选项即可。

然后执行 allure serve 生成的报告存放目录

⚠️ 参数化时 Allure history id 的计算规则

Allure 在计算 history id 时没有使用 ids 参数返回值,而是通过调用 repr 方法获取对象的规范字符串表示形式, 也就是说如果使用的是自定类进行参数化时,要确保 history id 正确计算,需要重写 __repr__ 方法。