Skip to content

Commit dd77c78

Browse files
add screenshot capture on test failure and create screenshots directory
1 parent 0ced258 commit dd77c78

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

tests/e2e-test/tests/conftest.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
import logging
1010
from bs4 import BeautifulSoup
1111
import atexit
12+
from datetime import datetime
13+
14+
# Create screenshots directory if it doesn't exist
15+
SCREENSHOTS_DIR = os.path.join(os.path.dirname(__file__), "screenshots")
16+
os.makedirs(SCREENSHOTS_DIR, exist_ok=True)
17+
print(f"Screenshots will be saved to: {SCREENSHOTS_DIR}") # Debug line
1218

1319
@pytest.fixture(scope="session")
1420
def login_logout():
@@ -51,9 +57,45 @@ def pytest_html_report_title(report):
5157

5258
@pytest.hookimpl(hookwrapper=True)
5359
def pytest_runtest_makereport(item, call):
60+
"""Generate test report with logs, subtest details, and screenshots on failure"""
5461
outcome = yield
5562
report = outcome.get_result()
5663

64+
# Capture screenshot on failure
65+
if report.when == "call" and report.failed:
66+
# Get the page fixture if it exists
67+
if "login_logout" in item.fixturenames:
68+
page = item.funcargs.get("login_logout")
69+
if page:
70+
try:
71+
# Generate screenshot filename with timestamp
72+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
73+
test_name = item.name.replace(" ", "_").replace("/", "_")
74+
screenshot_name = f"screenshot_{test_name}_{timestamp}.png"
75+
screenshot_path = os.path.join(SCREENSHOTS_DIR, screenshot_name)
76+
77+
# Take screenshot
78+
page.screenshot(path=screenshot_path)
79+
80+
# Add screenshot link to report
81+
if not hasattr(report, 'extra'):
82+
report.extra = []
83+
84+
# Add screenshot as a link in the Links column
85+
# Use relative path from report.html location
86+
relative_path = os.path.relpath(
87+
screenshot_path,
88+
os.path.dirname(os.path.abspath("report.html"))
89+
)
90+
91+
# pytest-html expects this format for extras
92+
from pytest_html import extras
93+
report.extra.append(extras.url(relative_path, name='Screenshot'))
94+
95+
logging.info("Screenshot saved: %s", screenshot_path)
96+
except Exception as exc: # pylint: disable=broad-exception-caught
97+
logging.error("Failed to capture screenshot: %s", str(exc))
98+
5799
handler, stream = log_streams.get(item.nodeid, (None, None))
58100

59101
if handler and stream:
@@ -65,8 +107,44 @@ def pytest_runtest_makereport(item, call):
65107
logger = logging.getLogger()
66108
logger.removeHandler(handler)
67109

68-
# Store the log output on the report object for HTML reporting
69-
report.description = f"<pre>{log_output.strip()}</pre>"
110+
# Check if there are subtests
111+
subtests_html = ""
112+
if hasattr(item, 'user_properties'):
113+
item_subtests = [
114+
prop[1] for prop in item.user_properties if prop[0] == "subtest"
115+
]
116+
if item_subtests:
117+
subtests_html = (
118+
"<div style='margin-top: 10px;'>"
119+
"<strong>Step-by-Step Details:</strong>"
120+
"<ul style='list-style: none; padding-left: 0;'>"
121+
)
122+
for idx, subtest in enumerate(item_subtests, 1):
123+
status = "✅ PASSED" if subtest.get('passed') else "❌ FAILED"
124+
status_color = "green" if subtest.get('passed') else "red"
125+
subtests_html += (
126+
f"<li style='margin: 10px 0; padding: 10px; "
127+
f"border-left: 3px solid {status_color}; "
128+
f"background-color: #f9f9f9;'>"
129+
)
130+
subtests_html += (
131+
f"<div style='font-weight: bold; color: {status_color};'>"
132+
f"{status} - {subtest.get('msg', f'Step {idx}')}</div>"
133+
)
134+
if subtest.get('logs'):
135+
subtests_html += (
136+
f"<pre style='margin: 5px 0; padding: 5px; "
137+
f"background-color: #fff; border: 1px solid #ddd; "
138+
f"font-size: 11px;'>{subtest.get('logs').strip()}</pre>"
139+
)
140+
subtests_html += "</li>"
141+
subtests_html += "</ul></div>"
142+
143+
# Combine main log output with subtests
144+
if subtests_html:
145+
report.description = f"<pre>{log_output.strip()}</pre>{subtests_html}"
146+
else:
147+
report.description = f"<pre>{log_output.strip()}</pre>"
70148

71149
# Clean up references
72150
log_streams.pop(item.nodeid, None)

0 commit comments

Comments
 (0)