书籍来源:房荔枝 梁丽丽《pytest框架与自动化测试应用》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:pytest框架进阶自学系列 | 汇总_热爱编程的通信人的博客-CSDN博客
使用yield代替return
已经可以将测试方法前要执行的或依赖的问题解决了,但测试方法后需要销毁并清除的数据该如何处理呢?范围是模块级别的,类似setupClass。解决方法是通过在同一模块中加入yield关键字,yield调用第一次返回结果,第二次执行它下面的语句并返回结果。
步骤如下:
(1)添加@pytest.fixture(scope=module)语句。
(2)在登录的方法中添加yield,之后添加销毁清除的步骤。
代码如下:
import pytest
@pytest.fixture(scope="module")
def open():
print("打开浏览器,打开百度首页")
yield
print("执行teardown")
print("最后关闭浏览器")
def test_s7():
print("用例7,")
def test_s8():
print("用例8,")
def test_s9(open):
print("用例9,")
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_fixture_module_yield.py
Testing started at 11:27 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_fixture_module_yield.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-3
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 3 items
test_fixture_module_yield.py::test_s7 PASSED [ 33%]用例7,
test_fixture_module_yield.py::test_s8 打开浏览器,打开百度首页
PASSED [ 66%]用例8,
test_fixture_module_yield.py::test_s9 PASSED [100%]用例9,
执行teardown
最后关闭浏览器
============================== 3 passed in 0.02s ==============================
Process finished with exit code 0
使用with写法
对于支持with写法的对象,程序也可以隐式地执行它的清理销毁操作。当使用with出现问题时,由Python进行处理以便销毁。
代码如下:
import smtplib
import pytest
@pytest.fixture()
def smtp_connection_yield():
with smtplib.SMTP("smtp.163.com", 25, timeout=5) as smtp_connection:
print("---start connection")
yield smtp_connection
print("---end connection")
def test_send_mail(smtp_connection_yield):
print("发邮件")
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_fixture_with.py
Testing started at 11:43 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_fixture_with.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-3
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 1 item
test_fixture_with.py::test_send_mail
============================== 1 passed in 0.17s ==============================
Process finished with exit code 0
---start connection
PASSED [100%]发邮件
---end connection
使用addfinalizer方法
fixture函数能够接收一个request参数,表示测试请求的上下文。本书使用request.addfinalizer方法为fixture添加清理销毁函数。
代码如下:
import pytest
@pytest.fixture()
def demo_fixture(request):
print("\n这个fixture在每个用例前执行一次")
def demo_finalizer():
print("\n在每个用例完成后执行的teardown")
request.addfinalizer(demo_finalizer)
def test_01(demo_fixture):
print("\n===执行了用例:test_01===")
def test_02(demo_fixture):
print("\n===执行了用例:test_02===")
def test_03(demo_fixture):
print("\n===执行了用例:test_03===")
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_addfinalizer.py
Testing started at 11:50 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_addfinalizer.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-3
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 3 items
test_addfinalizer.py::test_01
这个fixture在每个用例前执行一次
PASSED [ 33%]
===执行了用例:test_01===
在每个用例完成后执行的teardown
test_addfinalizer.py::test_02
这个fixture在每个用例前执行一次
PASSED [ 66%]
===执行了用例:test_02===
在每个用例完成后执行的teardown
test_addfinalizer.py::test_03
这个fixture在每个用例前执行一次
PASSED [100%]
===执行了用例:test_03===
在每个用例完成后执行的teardown
============================== 3 passed in 0.03s ==============================
Process finished with exit code 0
注意:如果在yield之前或者addfinalizer注册之前代码发生错误并退出,则不会再执行后续的清理操作。
yield与addfinalizer的区别
那么,除了在使用上的区别之外,yield与addfinalizer还有什么不同呢?
addfinalizer可以注册多个终结销毁函数,而yield无法实现多个。在执行yield的过程中出现错误无法再执行yield后面的函数,而addfinalizer函数在执行的过程中即使出错也会执行后面的函数。
代码如下:
import pytest
@pytest.fixture()
def demo_fixture(request):
print("\n这个fixture在每个用例前执行一次")
def demo_finalizer():
print("\n在每个用例完成后执行的teardown")
def demo_finalizer2():
print("\n在每个用例完成后执行的teardown2")
def demo_finalizer3():
print("\n在每个用例完成后执行的teardown3")
request.addfinalizer(demo_finalizer)
request.addfinalizer(demo_finalizer2)
request.addfinalizer(demo_finalizer3)
def test_01(demo_fixture):
print("\n===执行了用例:test_01===")
def test_02(demo_fixture):
print("\n===执行了用例:test_02===")
def test_03(demo_fixture):
print("\n===执行了用例:test_03===")
运行结果如图所示,可以看到,注册的3个函数都被执行了,但是要注意执行顺序,可以看出与注册的顺序恰好相反。
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_addfinalizer02.py
Testing started at 10:47 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-3/test_addfinalizer02.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-3
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 3 items
test_addfinalizer02.py::test_01
这个fixture在每个用例前执行一次
PASSED [ 33%]
===执行了用例:test_01===
在每个用例完成后执行的teardown3
在每个用例完成后执行的teardown2
在每个用例完成后执行的teardown
test_addfinalizer02.py::test_02
这个fixture在每个用例前执行一次
PASSED [ 66%]
===执行了用例:test_02===
在每个用例完成后执行的teardown3
在每个用例完成后执行的teardown2
在每个用例完成后执行的teardown
test_addfinalizer02.py::test_03
这个fixture在每个用例前执行一次
PASSED [100%]
===执行了用例:test_03===
在每个用例完成后执行的teardown3
在每个用例完成后执行的teardown2
在每个用例完成后执行的teardown
============================== 3 passed in 0.02s ==============================
Process finished with exit code 0
当setUp的代码执行出错时,addfinalizer依旧会被执行。