Skip to content

Commit 4092d0c

Browse files
committed
Improve Dashboard updates during multi-threaded mode
1 parent 84b16d3 commit 4092d0c

File tree

2 files changed

+145
-139
lines changed

2 files changed

+145
-139
lines changed

seleniumbase/fixtures/base_case.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10603,7 +10603,6 @@ def __process_dashboard(self, has_exception, init=False):
1060310603
out_file.close()
1060410604
sb_config._dash_html = the_html
1060510605
if self._multithreaded:
10606-
sb_config._dash_html_for_multithreading = the_html
1060710606
d_stats = (num_passed, num_failed, num_skipped, num_untested)
1060810607
_results = sb_config._results
1060910608
_display_id = sb_config._display_id

seleniumbase/plugins/pytest_plugin.py

Lines changed: 145 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,8 @@ def pytest_configure(config):
10861086
sb_config._duration = {} # SBase Dashboard test duration
10871087
sb_config._display_id = {} # SBase Dashboard display ID
10881088
sb_config._d_t_log_path = {} # SBase Dashboard test log path
1089-
sb_config._test_id = None # The SBase Dashboard test id
1089+
sb_config._dash_html = None # SBase Dashboard HTML copy
1090+
sb_config._test_id = None # SBase Dashboard test id
10901091
sb_config._latest_display_id = None # The latest SBase display id
10911092
sb_config._dashboard_initialized = False # Becomes True after init
10921093
sb_config._has_exception = False # This becomes True if any test fails
@@ -1324,16 +1325,7 @@ def pytest_terminal_summary(terminalreporter):
13241325
terminalreporter.write_sep("-", "LogPath: %s" % latest_logs_dir)
13251326

13261327

1327-
def pytest_unconfigure():
1328-
""" This runs after all tests have completed with pytest. """
1329-
if (
1330-
hasattr(sb_config, "_dash_html_for_multithreading")
1331-
and sb_config._multithreaded
1332-
):
1333-
abs_path = os.path.abspath(".")
1334-
dashboard_path = os.path.join(abs_path, "dashboard.html")
1335-
with open(dashboard_path, "w", encoding="utf-8") as f:
1336-
f.write(sb_config._dash_html)
1328+
def _perform_pytest_unconfigure_():
13371329
proxy_helper.remove_proxy_zip_if_present()
13381330
if hasattr(sb_config, "reuse_session") and sb_config.reuse_session:
13391331
# Close the shared browser session
@@ -1350,142 +1342,157 @@ def pytest_unconfigure():
13501342
sb_config.log_path, sb_config.archive_logs
13511343
)
13521344
# Dashboard post-processing: Disable time-based refresh and stamp complete
1353-
if sb_config._multithreaded and sb_config.dashboard:
1354-
abs_path = os.path.abspath(".")
1355-
dash_lock = constants.Dashboard.LOCKFILE
1356-
dash_lock_path = os.path.join(abs_path, dash_lock)
1357-
if os.path.exists(dash_lock_path):
1358-
sb_config._only_unittest = False
1359-
if hasattr(sb_config, "dashboard") and (
1360-
sb_config.dashboard and not sb_config._only_unittest
1361-
):
1362-
if sb_config._multithreaded:
1363-
import fasteners
1364-
1365-
dash_lock = fasteners.InterProcessLock(
1366-
constants.Dashboard.LOCKFILE
1367-
)
1368-
stamp = ""
1369-
if sb_config._dash_is_html_report:
1370-
# (If the Dashboard URL is the same as the HTML Report URL:)
1371-
# Have the html report refresh back to a dashboard on update
1372-
stamp += (
1373-
'\n<script type="text/javascript" src="%s">'
1374-
"</script>" % constants.Dashboard.LIVE_JS
1375-
)
1376-
stamp += "\n<!--Test Run Complete-->"
1377-
find_it = constants.Dashboard.META_REFRESH_HTML
1378-
swap_with = "" # Stop refreshing the page after the run is done
1379-
find_it_2 = "Awaiting results... (Refresh the page for updates)"
1380-
swap_with_2 = (
1381-
"Test Run ENDED: Some results UNREPORTED due to skipped tearDown()"
1345+
if not hasattr(sb_config, "dashboard") or not sb_config.dashboard:
1346+
# Done with "pytest_unconfigure" unless using the Dashboard
1347+
return
1348+
stamp = ""
1349+
if sb_config._dash_is_html_report:
1350+
# (If the Dashboard URL is the same as the HTML Report URL:)
1351+
# Have the html report refresh back to a dashboard on update
1352+
stamp += (
1353+
'\n<script type="text/javascript" src="%s">'
1354+
"</script>" % constants.Dashboard.LIVE_JS
13821355
)
1383-
find_it_3 = '<td class="col-result">Untested</td>'
1384-
swap_with_3 = '<td class="col-result">Unreported</td>'
1385-
find_it_4 = 'href="%s"' % constants.Dashboard.DASH_PIE_PNG_1
1386-
swap_with_4 = 'href="%s"' % constants.Dashboard.DASH_PIE_PNG_2
1387-
try:
1356+
stamp += "\n<!--Test Run Complete-->"
1357+
find_it = constants.Dashboard.META_REFRESH_HTML
1358+
swap_with = "" # Stop refreshing the page after the run is done
1359+
find_it_2 = "Awaiting results... (Refresh the page for updates)"
1360+
swap_with_2 = (
1361+
"Test Run ENDED: Some results UNREPORTED due to skipped tearDown()"
1362+
)
1363+
find_it_3 = '<td class="col-result">Untested</td>'
1364+
swap_with_3 = '<td class="col-result">Unreported</td>'
1365+
find_it_4 = 'href="%s"' % constants.Dashboard.DASH_PIE_PNG_1
1366+
swap_with_4 = 'href="%s"' % constants.Dashboard.DASH_PIE_PNG_2
1367+
try:
1368+
abs_path = os.path.abspath(".")
1369+
dashboard_path = os.path.join(abs_path, "dashboard.html")
1370+
# Part 1: Finalizing the dashboard / integrating html report
1371+
if os.path.exists(dashboard_path):
1372+
the_html_d = None
1373+
with open(dashboard_path, "r", encoding="utf-8") as f:
1374+
the_html_d = f.read()
1375+
if sb_config._multithreaded and "-c" in sys.argv:
1376+
# Threads have "-c" in sys.argv, except for the last
1377+
raise Exception('Break out of "try" block.')
13881378
if sb_config._multithreaded:
1389-
dash_lock.acquire()
1390-
abs_path = os.path.abspath(".")
1391-
dashboard_path = os.path.join(abs_path, "dashboard.html")
1392-
# Part 1: Finalizing the dashboard / integrating html report
1393-
if os.path.exists(dashboard_path):
1394-
the_html_d = None
1395-
with open(dashboard_path, "r", encoding="utf-8") as f:
1396-
the_html_d = f.read()
1397-
if sb_config._multithreaded and "-c" in sys.argv:
1398-
# Threads have "-c" in sys.argv, except for the last
1399-
raise Exception('Break out of "try" block.')
1400-
if sb_config._multithreaded:
1401-
dash_pie_loc = constants.Dashboard.DASH_PIE
1402-
pie_path = os.path.join(abs_path, dash_pie_loc)
1403-
if os.path.exists(pie_path):
1404-
import json
1379+
dash_pie_loc = constants.Dashboard.DASH_PIE
1380+
pie_path = os.path.join(abs_path, dash_pie_loc)
1381+
if os.path.exists(pie_path):
1382+
import json
14051383

1406-
with open(pie_path, "r") as f:
1407-
dash_pie = f.read().strip()
1408-
sb_config._saved_dashboard_pie = json.loads(dash_pie)
1409-
# If the test run doesn't complete by itself, stop refresh
1410-
the_html_d = the_html_d.replace(find_it, swap_with)
1411-
the_html_d = the_html_d.replace(find_it_2, swap_with_2)
1412-
the_html_d = the_html_d.replace(find_it_3, swap_with_3)
1413-
the_html_d = the_html_d.replace(find_it_4, swap_with_4)
1414-
the_html_d += stamp
1415-
if sb_config._dash_is_html_report and (
1416-
sb_config._saved_dashboard_pie
1417-
):
1418-
the_html_d = the_html_d.replace(
1419-
"<h1>dashboard.html</h1>",
1384+
with open(pie_path, "r") as f:
1385+
dash_pie = f.read().strip()
1386+
sb_config._saved_dashboard_pie = json.loads(dash_pie)
1387+
# If the test run doesn't complete by itself, stop refresh
1388+
the_html_d = the_html_d.replace(find_it, swap_with)
1389+
the_html_d = the_html_d.replace(find_it_2, swap_with_2)
1390+
the_html_d = the_html_d.replace(find_it_3, swap_with_3)
1391+
the_html_d = the_html_d.replace(find_it_4, swap_with_4)
1392+
the_html_d += stamp
1393+
if sb_config._dash_is_html_report and (
1394+
sb_config._saved_dashboard_pie
1395+
):
1396+
the_html_d = the_html_d.replace(
1397+
"<h1>dashboard.html</h1>",
1398+
sb_config._saved_dashboard_pie,
1399+
)
1400+
the_html_d = the_html_d.replace(
1401+
"</head>",
1402+
'</head><link rel="shortcut icon" '
1403+
'href="%s">' % constants.Dashboard.DASH_PIE_PNG_3,
1404+
)
1405+
the_html_d = the_html_d.replace(
1406+
"<html>", '<html lang="en">'
1407+
)
1408+
the_html_d = the_html_d.replace(
1409+
"<head>",
1410+
'<head><meta http-equiv="Content-Type" '
1411+
'content="text/html, charset=utf-8;">'
1412+
'<meta name="viewport" content="shrink-to-fit=no">',
1413+
)
1414+
if sb_config._dash_final_summary:
1415+
the_html_d += sb_config._dash_final_summary
1416+
time.sleep(0.1) # Add time for "livejs" to detect changes
1417+
with open(dashboard_path, "w", encoding="utf-8") as f:
1418+
f.write(the_html_d) # Finalize the dashboard
1419+
time.sleep(0.1) # Add time for "livejs" to detect changes
1420+
the_html_d = the_html_d.replace(
1421+
"</head>", "</head><!-- Dashboard Report Done -->"
1422+
)
1423+
with open(dashboard_path, "w", encoding="utf-8") as f:
1424+
f.write(the_html_d) # Finalize the dashboard
1425+
# Part 2: Appending a pytest html report with dashboard data
1426+
html_report_path = None
1427+
if sb_config._html_report_name:
1428+
html_report_path = os.path.join(
1429+
abs_path, sb_config._html_report_name
1430+
)
1431+
if (
1432+
sb_config._using_html_report
1433+
and html_report_path
1434+
and os.path.exists(html_report_path)
1435+
and not sb_config._dash_is_html_report
1436+
):
1437+
# Add the dashboard pie to the pytest html report
1438+
the_html_r = None
1439+
with open(html_report_path, "r", encoding="utf-8") as f:
1440+
the_html_r = f.read()
1441+
if sb_config._saved_dashboard_pie:
1442+
h_r_name = sb_config._html_report_name
1443+
if "/" in h_r_name and h_r_name.endswith(".html"):
1444+
h_r_name = h_r_name.split("/")[-1]
1445+
elif "\\" in h_r_name and h_r_name.endswith(".html"):
1446+
h_r_name = h_r_name.split("\\")[-1]
1447+
the_html_r = the_html_r.replace(
1448+
"<h1>%s</h1>" % h_r_name,
14201449
sb_config._saved_dashboard_pie,
14211450
)
1422-
the_html_d = the_html_d.replace(
1451+
the_html_r = the_html_r.replace(
14231452
"</head>",
1424-
'</head><link rel="shortcut icon" '
1425-
'href="%s">' % constants.Dashboard.DASH_PIE_PNG_3,
1426-
)
1427-
the_html_d = the_html_d.replace(
1428-
"<html>", '<html lang="en">'
1429-
)
1430-
the_html_d = the_html_d.replace(
1431-
"<head>",
1432-
'<head><meta http-equiv="Content-Type" '
1433-
'content="text/html, charset=utf-8;">'
1434-
'<meta name="viewport" content="shrink-to-fit=no">',
1453+
'</head><link rel="shortcut icon" href='
1454+
'"%s">' % constants.Dashboard.DASH_PIE_PNG_3,
14351455
)
14361456
if sb_config._dash_final_summary:
1437-
the_html_d += sb_config._dash_final_summary
1438-
time.sleep(0.1) # Add time for "livejs" to detect changes
1457+
the_html_r += sb_config._dash_final_summary
1458+
with open(html_report_path, "w", encoding="utf-8") as f:
1459+
f.write(the_html_r) # Finalize the HTML report
1460+
except KeyboardInterrupt:
1461+
pass
1462+
except Exception:
1463+
pass
1464+
1465+
1466+
def pytest_unconfigure():
1467+
""" This runs after all tests have completed with pytest. """
1468+
if sb_config._multithreaded:
1469+
import fasteners
1470+
1471+
dash_lock = fasteners.InterProcessLock(constants.Dashboard.LOCKFILE)
1472+
if (
1473+
hasattr(sb_config, "dashboard")
1474+
and sb_config.dashboard
1475+
and sb_config._dash_html
1476+
):
1477+
# Multi-threaded tests with the Dashboard
1478+
abs_path = os.path.abspath(".")
1479+
dash_lock_file = constants.Dashboard.LOCKFILE
1480+
dash_lock_path = os.path.join(abs_path, dash_lock_file)
1481+
if os.path.exists(dash_lock_path):
1482+
sb_config._only_unittest = False
1483+
dashboard_path = os.path.join(abs_path, "dashboard.html")
1484+
with dash_lock:
14391485
with open(dashboard_path, "w", encoding="utf-8") as f:
1440-
f.write(the_html_d) # Finalize the dashboard
1441-
time.sleep(0.1) # Add time for "livejs" to detect changes
1442-
the_html_d = the_html_d.replace(
1443-
"</head>", "</head><!-- Dashboard Report Done -->"
1444-
)
1445-
with open(dashboard_path, "w", encoding="utf-8") as f:
1446-
f.write(the_html_d) # Finalize the dashboard
1447-
# Part 2: Appending a pytest html report with dashboard data
1448-
html_report_path = None
1449-
if sb_config._html_report_name:
1450-
html_report_path = os.path.join(
1451-
abs_path, sb_config._html_report_name
1452-
)
1453-
if (
1454-
sb_config._using_html_report
1455-
and html_report_path
1456-
and os.path.exists(html_report_path)
1457-
and not sb_config._dash_is_html_report
1458-
):
1459-
# Add the dashboard pie to the pytest html report
1460-
the_html_r = None
1461-
with open(html_report_path, "r", encoding="utf-8") as f:
1462-
the_html_r = f.read()
1463-
if sb_config._saved_dashboard_pie:
1464-
h_r_name = sb_config._html_report_name
1465-
if "/" in h_r_name and h_r_name.endswith(".html"):
1466-
h_r_name = h_r_name.split("/")[-1]
1467-
elif "\\" in h_r_name and h_r_name.endswith(".html"):
1468-
h_r_name = h_r_name.split("\\")[-1]
1469-
the_html_r = the_html_r.replace(
1470-
"<h1>%s</h1>" % h_r_name,
1471-
sb_config._saved_dashboard_pie,
1472-
)
1473-
the_html_r = the_html_r.replace(
1474-
"</head>",
1475-
'</head><link rel="shortcut icon" href='
1476-
'"%s">' % constants.Dashboard.DASH_PIE_PNG_3,
1477-
)
1478-
if sb_config._dash_final_summary:
1479-
the_html_r += sb_config._dash_final_summary
1480-
with open(html_report_path, "w", encoding="utf-8") as f:
1481-
f.write(the_html_r) # Finalize the HTML report
1482-
except KeyboardInterrupt:
1483-
pass
1484-
except Exception:
1485-
pass
1486-
finally:
1487-
if sb_config._multithreaded:
1488-
dash_lock.release()
1486+
f.write(sb_config._dash_html)
1487+
_perform_pytest_unconfigure_()
1488+
return
1489+
with dash_lock:
1490+
# Multi-threaded tests
1491+
_perform_pytest_unconfigure_()
1492+
return
1493+
else:
1494+
# Single-threaded tests
1495+
_perform_pytest_unconfigure_()
14891496

14901497

14911498
@pytest.fixture()

0 commit comments

Comments
 (0)