fixture简介
fixture是在测试函数运行前后由pytest执行的外壳函数,可以定制包括定义传入测试中的数据集,配置测试前系统的初始状态、为批量测试提供数据源等等。fixture是pytest用于将测试前后进行预备,清理工作的代码分离出核心测试逻辑的机制。
@pytest.fixture()装饰器声明函数是一个fixture,如果测试函数的参数列表中包含fixture名,那么pytest就会检测到,并在运行测试函数之前运行它,fixture可以返回数据给测试函数。其优势在于编写测试函数时可以只考虑核心测试逻辑,而不需要考虑测试前的准备工作。
fixture使用
- 通过conftest.py共享fixture
fixture可以单独放在测试文件中,但是如果需要多个测试文件共享fixture,那么可以在其公共目录下新建一个conftest.py文件,将fixture放在其中。conftest可以看作pytest的一个本地插件库,不允许使用importconftest的用法,conftest的作用范围是其所在目录及其子目录。 - 使用fixture执行配置及销毁逻辑
fixture函数会在测试函数之前运行,但是如果fixture函数包含yield,那么会在yielf处停止并转而运行测试函数,等测试函数运行完毕后再回到该fixture继续执行yield后面的代码。可以将yield前面的代码看作是setup,yield后面的部分看作是teardown的过程。无论是测试函数中发生了什么,成功,失败或者error,yield后面的代码都会被执行,yield返回的数据可以在函数中使用。
#contentofconftest.py
importsmtplib
importpytest
@pytest.fixture(scope="module")
defsmtp_connection():
smtp_connection=smtplib.SMTP("smtp.gmail.com",587,timeout=5)
yieldsmtp_connection#providethefixturevalue
print("teardownsmtp")
smtp_connection.close()
如上所示,只需要在测试函数的参数中添加smtp_connection即可,defsmtp_connection()中的smtp_connection返回值也可以在测试函数中使用。在测试函数执行完毕后继续执行yield后面的语句。
- 使用--setup-show回溯fixture执行过程
pytest提供--setup-show可以看到测试过程中fixture的过程。结果中的S表示session即回话级别,M表示module级别,C表示class级别,F表示function级别。
fixture只能使用同级别或者比自己级别更高的fixture。比如,function级别的fixture使用同级别的fixture,也可以使用类级别、模块级别、会话级别的fixture,但是不可以反过来。 - fixture的作用范围
fixture有一个scope可选参数,默认为function,可选值为function、class、module、session。
function:表示每个测试函数只需要运行一次,配置代码在测试用例运行之前运行,销毁代码在测试用例之后运行。
class:表示每个测试类运行一次,无论测试类中有多少方法,都可以共享这个
fixture。
module: 表示每个模块运行一次,无论模块里有多少测试函数、类方法或者其他fixture都可以共享这个fixture。
session: 表示每次会话运行只需要运行一次,会话中的所有测试函数、方法都可以共享这个fixture。 - 使用usefuxtures指定fixture
可以在测试函数前使用 @pytest.mark.usefixtures(“fixture1”,“fixture2”) 标记测试函数或者测试类。与在测试方法中添加fixture参数差不多,但是使用usefixture不能使用fixture的返回值。 - fixture的参数化
在pytest中有一个内建的fixture叫做request,代表fixture的调用状态。request有一个字段param,可以使用类似 @pytest.fixture(param=task_list) 的方式,在fixture中使用request.param作为返回值供测试函数调用。其中tasks_list包含n个元素,该fixture就会被调用n次,分别作用在每个用到的测试函数上。
由于没有指定id,所以在输入时pytest会以fixture名加上数字作为标识,fixture也可以指定id,例如: @pytest.fixture(param=tasks_list,ids=task_ids)
ids可以是列表,也可以是函数供pytest生成task标识。