找回密码
 立即注册
首页 业界区 业界 高颜值测试报告 pytest-xhtml

高颜值测试报告 pytest-xhtml

扔飒 昨天 21:11
大概是三年前我自己设计了 XTestRunner 测试报告,主要是针对unittest 单元测试框架而设计。
1.jpeg

记得当时主要是被一个网友安利说 UnitTestReport 好看,这我就非常不服气了,你可以质疑我的技术能力,但是不能质疑我的审美,于是重新设计了XTestRunner并发布了 1.0 版本。至今为止,XTestRunner仍然是 unittest 最漂亮的第三方测试报告。
然而, 网友墙裂建议针对 pytest 单元测试框架支持一波,我当时专心搞seldom框架,才没心情支持。现在,终于乘上了了 XTestRunner 的 pytest 版本。
为什么要选择 pytest-xhtml?


  • Allure报告:需要额外安装Allure命令行工具,启动服务过于重量级,看个报告还要每台电脑都安装Allure命令。
  • pytest-html:界面太丑,这个看脸的世界,丑就是原罪。
pytest-xhtml特点


  • pytest-xhtml 基于 XTestRunner 的设计风格,将现代Web UI设计理念引入测试报告领域,实现了功能与美学的完美平衡。 - 这句是AI生成的。
  • pytest-xhtml 基于 pytest-html 魔改UI, 功能使用上与 pytest-html 保持一致,除了命名上有差异。使用 pytest-xhtml的时候,请卸载 pytest-html
安装方式


  • pip命令安装
  1. # 安装
  2. pip install pytest-xhtml
  3. #下面的示例会用到
  4. pip install pytest-req
  5. pip install selenium
复制代码
使用方式


  • 核心使用 - 与 pytest-html 完全一致
  1. pytest --html=report.html
复制代码
简单的单元测试

首先,配置 conftest.py文件,配置只是为了多显示两列内容,不配置也行。
  1. import pytest
  2. from datetime import datetime, timezone
  3. def pytest_xhtml_results_table_header(cells):
  4.     cells.insert(2, "<th>Description</th>")
  5.     cells.insert(1, '<th  data-column-type="time">Time</th>')
  6. def pytest_xhtml_results_table_row(report, cells):
  7.     cells.insert(2, f"<td>{report.description}</td>")
  8.     cells.insert(1, f'<td >{datetime.now(timezone.utc)}</td>')
  9. @pytest.hookimpl(hookwrapper=True)
  10. def pytest_runtest_makereport(item, call):
  11.     outcome = yield
  12.     report = outcome.get_result()
  13.     if hasattr(report, 'nodeid') and '::' in report.nodeid:
  14.         report.description = str(item.function.__doc__ or "No description")
复制代码
然后,编写测试用例 test_sample.py。
  1. import pytest
  2. # 简单的测试用例
  3. def test_pass():
  4.     assert 1 + 1 == 2
  5. def test_fail():
  6.     assert 1 + 1 == 3
  7. def test_skip():
  8.     pytest.skip("这个测试被跳过")
  9. @pytest.mark.xfail
  10. def test_xfail():
  11.     assert 1 + 1 == 3
  12. @pytest.mark.xfail(reason="预期失败,但实际会通过")
  13. def test_xpass():
  14.     """这是一个 Unexpected passes 用例 - 预期失败但实际通过"""
  15.     assert 1 + 1 == 2
  16. def test_error():
  17.     """这是一个 Error 用例 - 测试执行时发生异常"""
  18.     # 故意引发一个异常来模拟错误
  19.     raise ValueError("模拟测试执行错误")
  20. @pytest.fixture
  21. def error_fixture():
  22.     # 在fixture中引发异常,也会导致测试错误
  23.     raise RuntimeError("fixture中的错误")
  24. def test_error_with_fixture(error_fixture):
  25.     """使用会出错的fixture的测试用例"""
  26.     assert True
  27. if __name__ == '__main__':
  28.     pytest.main(["-v", "--html=report.html", "test_sample.py"])
复制代码
最后,运行测试用例。
  1. pytest -v --html=report.html test_sample.py
复制代码
2.png

HTTP接口测试

首先,配置 conftest.py文件,主要是为了显示接口调用日志信息。
  1. import pytest
  2. from datetime import datetime, timezone
  3. from datetime import datetime, timezone
  4. from pytest_req.log import log_cfg
  5. @pytest.fixture(scope="session", autouse=True)
  6. def setup_log():
  7.     """
  8.     setup log
  9.     """
  10.     log_format = "<green>{time:YYYY-MM-DD HH:mm:ss}</> |<level> {level} | {message}</level>"
  11.     log_cfg.set_level(format=log_format)
  12. def pytest_xhtml_results_table_header(cells):
  13.     cells.insert(2, "<th>Description</th>")
  14.     cells.insert(1, '<th  data-column-type="time">Time</th>')
  15. def pytest_xhtml_results_table_row(report, cells):
  16.     cells.insert(2, f"<td>{report.description}</td>")
  17.     cells.insert(1, f'<td >{datetime.now(timezone.utc)}</td>')
  18. @pytest.hookimpl(hookwrapper=True)
  19. def pytest_runtest_makereport(item, call):
  20.     outcome = yield
  21.     report = outcome.get_result()
  22.     if hasattr(report, 'nodeid') and '::' in report.nodeid:
  23.         report.description = str(item.function.__doc__ or "No description")
复制代码
然后,编写测试用例test_req.py。
  1. def test_post_method(post):
  2.     """
  3.     test post request
  4.     """
  5.     s = post('https://httpbin.org/post', data={'key': 'value'})
  6.     assert s.status_code == 200
  7. def test_get_method(get):
  8.     """
  9.     test get request
  10.     """
  11.     payload = {'key1': 'value1', 'key2': 'value2'}
  12.     s = get("https://httpbin.org/get", params=payload)
  13.     assert s.status_code == 200
  14. ...
复制代码
最后,运行测试用例。
  1. pytest -v --html=report.html test_sample.py
复制代码
3.png

Selenium UI测试

首先,配置 conftest.py文件, 主要是为了实现截图展示。
  1. import pytest
  2. from datetime import datetime, timezone
  3. from selenium import webdriver
  4. @pytest.fixture
  5. def driver():
  6.     """提供 WebDriver 实例用于测试"""
  7.     driver = webdriver.Edge()
  8.     yield driver
  9.     driver.quit()
  10. def pytest_xhtml_results_table_header(cells):
  11.     cells.insert(2, "<th>Description</th>")
  12.     cells.insert(1, '<th  data-column-type="time">Time</th>')
  13. def pytest_xhtml_results_table_row(report, cells):
  14.     cells.insert(2, f"<td>{report.description}</td>")
  15.     cells.insert(1, f'<td >{datetime.now(timezone.utc)}</td>')
  16. @pytest.hookimpl(hookwrapper=True)
  17. def pytest_runtest_makereport(item, call):
  18.     outcome = yield
  19.     report = outcome.get_result()
  20.    
  21.     # 只为测试用例添加描述,不处理收集阶段的报告
  22.     if hasattr(report, 'nodeid') and '::' in report.nodeid:
  23.         report.description = str(item.function.__doc__ or "No description")
  24.    
  25.     # 当测试失败时添加截图
  26.     if report.when == "call" and report.failed:
  27.         # 获取当前测试的 driver fixture
  28.         driver = item.funcargs.get('driver')
  29.         if driver:
  30.             # 使用 base64 编码获取截图
  31.             screenshot_base64 = driver.get_screenshot_as_base64()
  32.             
  33.             # 将截图添加到报告额外信息中 - 使用 pytest-xhtml 期望的格式
  34.             if not hasattr(report, 'extras'):
  35.                 report.extras = []
  36.             
  37.             # 使用 pytest-xhtml 支持的格式
  38.             report.extras.append({
  39.                 'name': 'Screenshot',
  40.                 'format_type': 'image',  # 必需字段
  41.                 'content': screenshot_base64,  # base64 内容
  42.                 'mime_type': 'image/png',  # 必需字段
  43.                 'extension': 'png'  # 必需字段
  44.             })
复制代码
然后,编写测试用例test_req.py。
  1. from time import sleep
  2. from selenium.webdriver.common.by import By
  3. def test_bing_search_fail(driver):
  4.     """测试 Bing 搜索功能"""
  5.     # 访问 Bing 搜索页面
  6.     driver.get("https://www.bing.com")
  7.     sleep(2)
  8.     assert driver.title == "pytest-xhtml - 搜索11"
  9. ...
复制代码
最后,运行测试用例。
  1. pytest -v --html=report.html test_selenium.py
复制代码
4.png

最后说明

pytest-xhtml 调样式前后花费了一周(晚上)时间,相比较 XTestRunner 缺失一些统计图表。后面再慢慢增加吧!功能上可以完全替代 pytest-html 了,快去体验一下吧!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册