首先, conftest.py
的文件名称是固定的, pytest
会自动识别该文件,我们可以理解成一个专门存放 fixture
的配置文件。
一个工程下可以建多个 conftest.py
文件,一般我们都是在工程根目录下设置的 conftest
文件,这样会起到一个全局的作用。 我们也可以在不同的子目录下放 conftest.py
,这样作用范围只能在该层级的子目录下生效。
conftest.py 配置 fixture 注意事项:
conftest.py
的文件#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/22 13:23
# @Author : 余少琪
import pytest
"""
scope:
1、scope 默认是function,只要是函数都会运行
2、class 类级别,每个函数都会运行一次
3、session 整个作用域只运行一次
4、module 整个py文件(模块)作用域只运行一次
autouse: 是否自动调用
"""
@pytest.fixture(scope='session', autouse=True)
def login_init():
print("这里返回了一个token")
conftest.py
文件的根目录下在创建一个 test_demo.py
文件import pytest
def test_aaa():
print("这里是aaa函数")
if __name__ == '__main__':
pytest.main(['test_demo.py', '-s'])
我们来查看一下执行结果:
pytest在执行 test_demo.py
文件之前,会先执行 conftest.py
文件中的方法,然后在执行 test_demo.py
文件。
============================= test session starts =============================
platform win32 -- Python 3.8.8, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: C:\Users\hzxy\PycharmProjects\pytest_api_demo, configfile: pytest.ini
plugins: allure-pytest-2.9.45
collected 1 item
test_demo.py 这里返回了一个token
这里是aaa函数
.
============================== 1 passed in 0.02s ==============================
用 fixture
实现 teardown
并不是一个独立的函数,而是用 yield
关键字来开启 teardown
操作。
当 pytest.fixture(scope="session")
时,作用域是整个测试会话,即开始执行pytest
到结束测试只会执行一次。
当 pytest.fixture(scope="function")
时,pytest
的 yield
类似 unittest
的 teardown
。每个方法(函数)都会执行一次。
当 pytest.fixture(scope="module")
时, module
作用是整个 .py 文件都会生效(整个文件只会执行一次),用例调用时,参数写上函数名称就可以。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/25 10:50
# @Author : 余少琪
import pytest
import pytest
@pytest.fixture(scope="session")
def open():
# 会话前置操作setup
print("===开始执行测试用例===")
yield
# 会话后置操作teardown
print("===测试用例执行完成===")
@pytest.fixture
def login(open):
# 方法级别前置操作setup
print("===登陆操作login===")
name = "===账号==="
pwd = "===密码==="
# 返回变量
yield name, pwd
# 方法级别后置操作teardown
print("===登录成功login===")
def test_case1(login):
print("===测试用例1===")
# 返回的是一个元组
print(login)
# 分别赋值给不同变量
name, pwd = login
print(name, pwd)
assert "账号" in name
assert "密码" in pwd
def test_case2(login):
print("===测试用例2===")
print(login)
if __name__ == '__main__':
pytest.main(['test_demo.py', '-s'])
我们来查看一下执行结果:
============================= test session starts =============================
platform win32 -- Python 3.8.8, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: C:\Users\hzxy\PycharmProjects\pytest_api_demo, configfile: pytest.ini
plugins: allure-pytest-2.9.45
collected 2 items
test_demo.py 这里返回了一个token
===开始执行测试用例===
===登陆操作login===
===测试用例1===
('===账号===', '===密码===')
===账号=== ===密码===
.===登录成功login===
===登陆操作login===
===测试用例2===
('===账号===', '===密码===')
.===登录成功login===
===测试用例执行完成===
============================== 2 passed in 0.03s ==============================
注意
:
yield 也可以配合 with 语句使用。
import pytest
import smtplib
@pytest.fixture(scope="module")
def smtp_connection():
with smtplib.SMTP("smtp.gmail.com", 587, timeout=5) as smtp_connection:
# 在 yield 后面添加smtp_connection,则类似 return,返回 smtp_connection信息
yield smtp_connection
除了 yield
可以实现 teardown
,在 request-context
对象中注册 addfinalizer
方法也可以实现终结函数。
在用法上, addfinalizer
跟 yield
是不同的,需要你去注册作为终结器使用的函数。例如:增加一个函数 fin
,并且注册成终结函数。
import pytest
@pytest.fixture(scope="module")
def test_addfinalizer(request):
# 前置操作setup
print("===打开浏览器===")
test = "test_addfinalizer"
def fin():
# 后置操作teardown
print("===关闭浏览器===")
request.addfinalizer(fin)
# 返回前置操作的变量
return test
def test_case(test_addfinalizer):
print("===最新用例===", test_addfinalizer)
返回结果:
============================= test session starts =============================
platform win32 -- Python 3.8.8, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: C:\Users\hzxy\PycharmProjects\pytest_api_demo, configfile: pytest.ini
plugins: allure-pytest-2.9.45
collected 1 item
test_demo.py 这里返回了一个token
===打开浏览器===
===最新用例=== test_addfinalizer
.===关闭浏览器===
============================== 1 passed in 0.02s ==============================
yield 与 addfinalizer 的区别:
addfinalizer 可以注册多个终结函数。
import pytest
@pytest.fixture()
def demo_addfinalizer(request):
print("====setup====")
def fin1():
print("====teardown1====")
def fin2():
print("====teardown2====")
def fin3():
print("====teardown3====")
# 注册demo_addfinalizer为终结函数
request.addfinalizer(fin1)
request.addfinalizer(fin2)
request.addfinalizer(fin3)
def test_case1(demo_addfinalizer):
print("====执行用例test_case1====")
def test_case2(demo_addfinalizer):
print("====执行用例test_case2====")
def test_case3(demo_addfinalizer):
print("====执行用例test_case3====")
if __name__ == '__main__':
pytest.main(['test_demo.py', '-s'])
返回结果:
============================= test session starts =============================
platform win32 -- Python 3.8.8, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: C:\Users\hzxy\PycharmProjects\pytest_api_demo, configfile: pytest.ini
plugins: allure-pytest-2.9.45
collected 3 items
test_demo.py 这里返回了一个token
====setup====
====执行用例test_case1====
.====teardown3====
====teardown2====
====teardown1====
====setup====
====执行用例test_case2====
.====teardown3====
====teardown2====
====teardown1====
====setup====
====执行用例test_case3====
.====teardown3====
====teardown2====
====teardown1====
============================== 3 passed in 0.04s ==============================