前言
用例执行完成后,我们希望能获取到执行的结果,这样方便我们快速统计用例的执行情况。
也可以把获取到的结果当成总结报告,发邮件的时候可以先统计测试结果,再加上html的报告。
pytest_terminal_summary源码
关于 TerminalReporter 类可以在 _pytest.terminal 中查看到:
from _pytest import terminal pytest_terminal_summary(terminalreporter, exitstatus, config) 最后的结果汇总,可以拿到所有的执行结果
参数: - terminalreporter (_pytest.terminal.TerminalReporter) – 内部使用的终端测试报告对象 - exitstatus (int) – 返回给操作系统的返回码 - config(_pytest.config.Config) - pytest config对象
案例参考
test_a.py:
# test_a.py import pytest def test_1(): print("测试用例1111") assert 1 == 1 @pytest.mark.skip("跳过") def test_2(): print("测试用例22222") assert 1 == 1 def test_3(): print("测试用例3333") def test_4(): print("测试用例44444444") assert 1 == 2
test_b.py:
# test_b.py import time def test_5(): print("测试用例55555555") time.sleep(3) def test_6(): print("测试用例66666666") time.sleep(3) assert 1 == 2
于是在conftest.py中写个 pytest_terminal_summary 函数收集测试结果:
import time from _pytest import terminal def pytest_terminal_summary(terminalreporter, exitstatus, config): '''收集测试结果''' print(terminalreporter.stats) print("total:", terminalreporter._numcollected) print('passed:', len(terminalreporter.stats.get('passed', []))) print('failed:', len(terminalreporter.stats.get('failed', []))) print('error:', len(terminalreporter.stats.get('error', []))) print('skipped:', len(terminalreporter.stats.get('skipped', []))) # terminalreporter._sessionstarttime 会话开始时间 duration = time.time() - terminalreporter._sessionstarttime print('total times:', duration, 'seconds')
运行结果:
D:\soft\pytest_xuexi_demo>pytest ============================= test session starts ============================= platform win32 -- Python 3.6.0, pytest-4.5.0, py-1.5.4, pluggy-0.13.1 rootdir: D:\soft\pytest_xuexi_demo plugins: allure-pytest-2.8.6, PyTestReport-0.1.9.3, forked-0.2, html-1.19.0, metadata-1.7.0, repeat-0.7.0, rerunfailures-8.0, xdist-1.23.2 collected 6 items test_a.py .s.F [ 66%] test_b.py .F [100%] ================================== FAILURES =================================== ___________________________________ test_4 ____________________________________ def test_4(): print("测试用例44444444") > assert 1==2 E assert 1 == 2 test_a.py:21: AssertionError ---------------------------- Captured stdout call ----------------------------- 测试用例44444444 ___________________________________ test_6 ____________________________________ def test_6(): print("测试用例66666666") time.sleep(3) > assert 1 == 2 E assert 1 == 2 test_b.py:18: AssertionError ---------------------------- Captured stdout call ----------------------------- 测试用例66666666 {'': [<TestReport 'test_a.py::test_1' when='setup' outcome='passed'>, <TestReport 'test_a.py::test_1' when='teardown' outcome='passed'>, <TestReport 'test_a.py::test_2' when='teardown' outcome='passed'>, <TestReport 'test_a.py::test_3' when='setup' outcome='passed'>, <TestReport 'test_a.py::test_3' when='teardown' outcome='passed'>, <TestReport 'test_a.py::test_4' when='setup' outcome='passed'>, <TestReport 'test_a.py::test_4' when='teardown' outcome='passed'>, <TestReport 'test_b.py::test_5' when='setup' outcome='passed'>, <TestReport 'test_b.py::test_5' when='teardown' outcome='passed'>, <TestReport 'test_b.py::test_6' when='setup' outcome='passed'>, <TestReport 'test_b.py::test_6' when='teardown' outcome='passed'>], 'passed': [<TestReport 'test_a.py::test_1' when='call' outcome='passed'>, <TestReport 'test_a.py::test_3' when='call' outcome='passed'>, <TestReport 'test_b.py::test_5' when='call' outcome='passed'>], 'skipped': [<TestReport 'test_a.py::test_2' when='setup' outcome='skipped'>], 'failed': [<TestReport 'test_a.py::test_4' when='call' outcome='failed'>, <TestReport 'test_b.py::test_6' when='call' outcome='failed'>]} total: 6 passed: 3 failed: 2 error: 0 skipped: 1 total times: 6.150860786437988 seconds ================ 2 failed, 3 passed, 1 skipped in 6.15 seconds ================
setup和teardown异常情况
如果setup出现异常,test_b.py代码修改下:
# test_b.py import time import pytest @pytest.fixture(scope="function") def setup_demo(): raise TypeError("ERROR!") def test_5(setup_demo): print("测试用例55555555") time.sleep(3) def test_6(): print("测试用例66666666") time.sleep(3) assert 1 == 2
重新运行用例,结果如下:
total: 6 passed: 2 failed: 2 error: 1 skipped: 1 成功率:33.33% total times: 3.1817877292633057 seconds =========== 2 failed, 2 passed, 1 skipped, 1 error in 3.18 seconds ============
此时统计结果没什么问题,接下来看teardown异常情况:
# test_b.py
import time import pytest @pytest.fixture(scope="function") def setup_demo(): yield raise TypeError("ERROR!") def test_5(setup_demo): print("测试用例55555555") time.sleep(3) def test_6(): print("测试用例66666666") time.sleep(3) assert 1 == 2
运行结果:
{'': [<TestReport 'test_a.py::test_1' when='setup' outcome='passed'>, <TestReport 'test_a.py::test_1' when='teardown' outcome='passed'>, <TestReport 'test_a.py::test_2' when='teardown' outcome='passed'>, <TestReport 'test_a.py::test_3' when='setup' outcome='passed'>, <TestReport 'test_a.py::test_3' when='teardown' outcome='passed'>, <TestReport 'test_a.py::test_4' when='setup' outcome='passed'>, <TestReport 'test_a.py::test_4' when='teardown' outcome='passed'>, <TestReport 'test_b.py::test_5' when='setup' outcome='passed'>, <TestReport 'test_b.py::test_6' when='setup' outcome='passed'>, <TestReport 'test_b.py::test_6' when='teardown' outcome='passed'>], 'passed': [<TestReport 'test_a.py::test_1' when='call' outcome='passed'>, <TestReport 'test_a.py::test_3' when='call' outcome='passed'>, <TestReport 'test_b.py::test_5' when='call' outcome='passed'>], 'skipped': [<TestReport 'test_a.py::test_2' when='setup' outcome='skipped'>], 'failed': [<TestReport 'test_a.py::test_4' when='call' outcome='failed'>, <TestReport 'test_b.py::test_6' when='call' outcome='failed'>], 'error': [<TestReport 'test_b.py::test_5' when='teardown' outcome='failed'>]} total: 6 passed: 3 failed: 2 error: 1 skipped: 1 成功率:50.00% total times: 6.18759298324585 seconds =========== 2 failed, 3 passed, 1 skipped, 1 error in 6.19 seconds ============
拿到测试结果
如何拿到测试结果,这里将测试结果保存为txt文件,你们也可以保存json文件。
import time from _pytest import terminal # blog地址 https://www.cnblogs.com/yoyoketang/ def pytest_terminal_summary(terminalreporter, exitstatus, config): '''收集测试结果''' # print(terminalreporter.stats) total = terminalreporter._numcollected passed= len([i for i in terminalreporter.stats.get('passed', []) if i.when != 'teardown']) failed=len([i for i in terminalreporter.stats.get('failed', []) if i.when != 'teardown']) error=len([i for i in terminalreporter.stats.get('error', []) if i.when != 'teardown']) skipped=len([i for i in terminalreporter.stats.get('skipped', []) if i.when != 'teardown']) successful = len(terminalreporter.stats.get('passed', []))/terminalreporter._numcollected*100 # terminalreporter._sessionstarttime 会话开始时间 duration = time.time() - terminalreporter._sessionstarttime print('total times: %.2f' % duration, 'seconds') with open("result.txt", "w") as fp: fp.write("TOTAL=%s" % total+"\n") fp.write("PASSED=%s" % passed+"\n") fp.write("FAILED=%s" % failed+"\n") fp.write("ERROR=%s" % error+"\n") fp.write("SKIPPED=%s" % skipped+"\n") fp.write("SUCCESSFUL=%.2f%%" % successful+"\n") fp.write("TOTAL_TIMES=%.2fs" % duration)
邮件发送
邮件发送是配合jenkins发送邮件,可以参考这篇https://www.cnblogs.com/yoyoketang/p/14956235.html