我将 pytest 与 pytest-html 插件结合使用,该插件在测试运行后生成 HTML 报告。
我使用自动连接的会话固定装置自动打开生成的 HTML 报告浏览器:
@pytest.fixture(scope="session", autouse=True)
def session_wrapper(request):
print('Session wrapper init...')
yield
# open report in browser on Mac or Windows, skip headless boxes
if platform.system() in ['Darwin', 'Windows']:
html_report_path = os.path.join(request.config.invocation_dir.strpath, request.config.option.htmlpath)
open_url_in_browser("file://%s" %html_report_path)
上面的代码可以工作,但不一致,因为有时浏览器会在创建文件之前尝试加载文件,这会导致文件未找到错误,并且需要手动刷新浏览器才能显示报告.
我的理解是
scope="session"
是最广泛的可用范围,我的假设是 pytest-html 应该在会话结束之前完成生成报告,但显然情况并非如此。
问题是:挂钩浏览器报告自动启动代码的正确方法是什么?难道
pytest-html
也挂接到会话终结器作用域中?在这种情况下,如何确保 HTML 文件仅在创建文件后才在浏览器中打开?
你对 pytest-html 的行为的理解是正确的。它确实挂接到会话范围,但是报告生成在会话结束时异步发生。这就是为什么你的浏览器试图在报告准备就绪之前加载它的原因。
你可以通过以下几种方式解决此问题:
1. 使用
pytest-html
的
on_report_generation
挂钩:
pytest-html 插件提供了一个
on_report_generation
挂钩,它在报告生成
之后
被调用。你可以在你的
conftest.py
文件中使用这个挂钩来可靠地打开报告:
```python from pytest_html import plugin as html_plugin
@html_plugin.on_report_generation def on_report_generation(report, config): if platform.system() in ['Darwin', 'Windows']: html_report_path = os.path.join(config.invocation_dir.strpath, config.option.htmlpath) open_url_in_browser("file://%s" % html_report_path) ```
这个方法确保浏览器仅在报告完全生成后才会尝试打开它。
2. 使用
time.sleep
引入延迟(不推荐):
虽然这不是最优雅的解决方案,但你可以添加一个小的延迟来为报告生成提供时间,然后再尝试打开它:
```python import time
@pytest.fixture(scope="session", autouse=True) def session_wrapper(request): # ... 你的现有代码 ...
# 在尝试打开之前,短暂等待报告生成
if platform.system() in ['Darwin', 'Windows']:
time.sleep(5) # 等待 5 秒
html_report_path = os.path.join(request.config.invocation_dir.strpath, request.config.option.htmlpath)
open_url_in_browser("file://%s" % html_report_path)
```
这个方法有效,但不准确,并可能导致不必要的延迟。
3. 使用独立的进程打开报告:
你可以使用
subprocess
模块在一个单独的进程中打开报告。这确保在尝试打开浏览器之前你的测试会话完全关闭:
```python import subprocess
@pytest.fixture(scope="session", autouse=True) def session_wrapper(request): # ... 你的现有代码 ...
if platform.system() in ['Darwin', 'Windows']:
html_report_path = os.path.join(request.config.invocation_dir.strpath, request.config.option.htmlpath)
subprocess.Popen(["open", html_report_path]) # 在 macOS 上使用 "open",在 Windows 上使用 "start"
```
此方法避免了计时问题,并确保报告在浏览器中正确打开。
我建议使用
on_report_generation
挂钩(选项 1)
来获得最可靠和最优雅的解决方案。它保证浏览器仅在报告准备好后才会打开,并且不会引入不必要的延迟或进程管理开销。