Skip to content

Commit cb63dae

Browse files
authored
Merge pull request #754 from seleniumbase/update-dashboards
Improve the SeleniumBase Dashboard functionality
2 parents def2813 + dcab576 commit cb63dae

File tree

8 files changed

+133
-30
lines changed

8 files changed

+133
-30
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ pytest test_demo_site.py
457457
```
458458
459459
460-
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Logging / Results from Failing Tests:</h3>
460+
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Log files from failed tests:</h3>
461461
462462
Let's try an example of a test that fails:
463463
@@ -484,7 +484,11 @@ You'll notice that a logs folder, "latest_logs", was created to hold information
484484
485485
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> The SeleniumBase Dashboard:</h3>
486486
487-
The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results.
487+
The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results. Example:
488+
489+
```bash
490+
pytest --dashboard --rs --headless
491+
```
488492
489493
<img src="https://seleniumbase.io/cdn/img/dashboard_1.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="360" />
490494
@@ -494,7 +498,7 @@ Additionally, you can host your own SeleniumBase Dashboard Server on a port of y
494498
python -m http.server 1948
495499
```
496500
497-
Now you can navigate to ``http://localhost:1948/dashboard.html`` in order to view the served dashboard from a web browser. (Be sure to run that command in the same directory where you ran your tests.)
501+
Now you can navigate to ``http://localhost:1948/dashboard.html`` in order to view the dashboard as a web app. This requires two different terminal windows: one for running the server, and another for running the tests, which should be run from the same directory.
498502
499503
Here's a full example of what the SeleniumBase Dashboard may look like:
500504
@@ -507,7 +511,7 @@ pytest test_suite.py --dashboard --rs --headless
507511
--------
508512
509513
<a id="creating_visual_reports"></a>
510-
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Creating Visual Test Suite Reports:</h3>
514+
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Creating Visual Test Reports:</h3>
511515
512516
<h4><b>Pytest Reports:</b></h4>
513517
@@ -519,6 +523,10 @@ pytest test_suite.py --html=report.html
519523
520524
<img src="https://seleniumbase.io/cdn/img/html_report.png" alt="Example Pytest Report" title="Example Pytest Report" width="520" />
521525
526+
When combining pytest html reports with SeleniumBase Dashboard usage, the pie chart from the Dashboard will get added to the html report. Additionally, if you set the html report URL to be the same as the Dashboard URL when also using the dashboard, (example: ``--dashboard --html=dashboard.html``), then the Dashboard will become an advanced html report when all the tests complete.
527+
528+
If viewing pytest html reports in [Jenkins](https://www.jenkins.io/), you may need to [configure Jenkins settings](https://stackoverflow.com/a/46197356) for the html to render correctly. This is due to [Jenkins CSP changes](https://www.jenkins.io/doc/book/system-administration/security/configuring-content-security-policy/).
529+
522530
You can also use ``--junit-xml=report.xml`` to get an xml report instead. Jenkins can use this file to display better reporting for your tests.
523531
524532
```bash

examples/example_logs/ReadMe.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ nosetests test_fail.py --browser=firefox
2323

2424
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> The SeleniumBase Dashboard:</h3>
2525

26-
The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results.
26+
The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results. Example:
27+
28+
```bash
29+
pytest --dashboard --rs --headless
30+
```
2731

2832
<img src="https://seleniumbase.io/cdn/img/dashboard_1.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="360" />
2933

@@ -33,7 +37,7 @@ Additionally, you can host your own SeleniumBase Dashboard Server on a port of y
3337
python -m http.server 1948
3438
```
3539

36-
Now you can navigate to ``http://localhost:1948/dashboard.html`` in order to view the served dashboard from a web browser. (Be sure to run that command in the same directory where you ran your tests.)
40+
Now you can navigate to ``http://localhost:1948/dashboard.html`` in order to view the dashboard as a web app. This requires two different terminal windows: one for running the server, and another for running the tests, which should be run from the same directory.
3741

3842
Here's a full example of what the SeleniumBase Dashboard may look like:
3943

@@ -55,8 +59,16 @@ pytest test_suite.py --html=report.html
5559

5660
<img src="https://seleniumbase.io/cdn/img/html_report.png" alt="Example Pytest Report" title="Example Pytest Report" width="520" />
5761

62+
When combining pytest html reports with SeleniumBase Dashboard usage, the pie chart from the Dashboard will get added to the html report. Additionally, if you set the html report URL to be the same as the Dashboard URL when also using the dashboard, (example: ``--dashboard --html=dashboard.html``), then the Dashboard will become an advanced html report when all the tests complete.
63+
5864
If viewing pytest html reports in [Jenkins](https://www.jenkins.io/), you may need to [configure Jenkins settings](https://stackoverflow.com/a/46197356) for the html to render correctly. This is due to [Jenkins CSP changes](https://www.jenkins.io/doc/book/system-administration/security/configuring-content-security-policy/).
5965

66+
You can also use ``--junit-xml=report.xml`` to get an xml report instead. Jenkins can use this file to display better reporting for your tests.
67+
68+
```bash
69+
pytest test_suite.py --junit-xml=report.xml
70+
```
71+
6072
--------
6173

6274
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Nosetest Reports:</h3>

help_docs/customizing_test_runs.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,11 @@ The code above will leave your browser window open in case there's a failure. (i
260260

261261
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> The SeleniumBase Dashboard:</h3>
262262

263-
The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results.
263+
The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results. Example:
264+
265+
```bash
266+
pytest --dashboard --rs --headless
267+
```
264268

265269
<img src="https://seleniumbase.io/cdn/img/dashboard_1.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="360" />
266270

@@ -270,7 +274,7 @@ Additionally, you can host your own SeleniumBase Dashboard Server on a port of y
270274
python -m http.server 1948
271275
```
272276

273-
Now you can navigate to ``http://localhost:1948/dashboard.html`` in order to view the served dashboard from a web browser. (Be sure to run that command in the same directory where you ran your tests.)
277+
Now you can navigate to ``http://localhost:1948/dashboard.html`` in order to view the dashboard as a web app. This requires two different terminal windows: one for running the server, and another for running the tests, which should be run from the same directory.
274278

275279
Here's a full example of what the SeleniumBase Dashboard may look like:
276280

@@ -282,7 +286,7 @@ pytest test_suite.py --dashboard --rs --headless
282286

283287
--------
284288

285-
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="28" /> Pytest Reports:</h3>
289+
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Pytest Reports:</h3>
286290

287291
Using ``--html=report.html`` gives you a fancy report of the name specified after your test suite completes.
288292

@@ -292,6 +296,16 @@ pytest test_suite.py --html=report.html
292296

293297
<img src="https://seleniumbase.io/cdn/img/html_report.png" alt="Example Pytest Report" title="Example Pytest Report" width="520" />
294298

299+
When combining pytest html reports with SeleniumBase Dashboard usage, the pie chart from the Dashboard will get added to the html report. Additionally, if you set the html report URL to be the same as the Dashboard URL when also using the dashboard, (example: ``--dashboard --html=dashboard.html``), then the Dashboard will become an advanced html report when all the tests complete.
300+
301+
If viewing pytest html reports in [Jenkins](https://www.jenkins.io/), you may need to [configure Jenkins settings](https://stackoverflow.com/a/46197356) for the html to render correctly. This is due to [Jenkins CSP changes](https://www.jenkins.io/doc/book/system-administration/security/configuring-content-security-policy/).
302+
303+
You can also use ``--junit-xml=report.xml`` to get an xml report instead. Jenkins can use this file to display better reporting for your tests.
304+
305+
```bash
306+
pytest test_suite.py --junit-xml=report.xml
307+
```
308+
295309
--------
296310

297311
<h3><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="28" /> Nosetest Reports:</h3>

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ toml==0.10.2
7272
Pillow==6.2.2;python_version<"3.5"
7373
Pillow==7.2.0;python_version>="3.5" and python_version<"3.6"
7474
Pillow==8.0.1;python_version>="3.6"
75-
rich==9.4.0;python_version>="3.6" and python_version<"4.0"
75+
rich==9.5.1;python_version>="3.6" and python_version<"4.0"
7676
zipp==1.2.0;python_version<"3.6"
7777
zipp==3.4.0;python_version>="3.6"
7878
flake8==3.7.9;python_version<"3.5"

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "1.51.0"
2+
__version__ = "1.51.1"

seleniumbase/fixtures/base_case.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6735,6 +6735,11 @@ def __process_dashboard(self, has_exception, init=False):
67356735
if num_untested > 0:
67366736
# Refresh every X seconds when waiting for more test results
67376737
auto_refresh_html = constants.Dashboard.META_REFRESH_HTML
6738+
else:
6739+
# The tests are complete
6740+
if sb_config._using_html_report:
6741+
# Add the pie chart to the pytest html report
6742+
sb_config._saved_dashboard_pie = self.extract_chart()
67386743
head = (
67396744
'<head><meta charset="utf-8" />'
67406745
'<meta property="og:image" '
@@ -6832,6 +6837,8 @@ def __process_dashboard(self, has_exception, init=False):
68326837
refresh_line = (
68336838
'<script type="text/javascript" src="%s">'
68346839
'</script>' % constants.Dashboard.LIVE_JS)
6840+
if num_untested == 0 and sb_config._using_html_report:
6841+
sb_config._dash_final_summary = status
68356842
add_more = add_more + refresh_line
68366843
the_html = head + self.extract_chart() + table_html + add_more
68376844
abs_path = os.path.abspath('.')

seleniumbase/plugins/pytest_plugin.py

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -594,10 +594,21 @@ def pytest_configure(config):
594594
sb_config._only_unittest = True # If any test uses BaseCase, becomes False
595595
sb_config._sbase_detected = False # Becomes True during SeleniumBase tests
596596
sb_config._extra_dash_entries = [] # Dashboard entries for non-SBase tests
597+
sb_config._using_html_report = False # Becomes True when using html report
598+
sb_config._dash_is_html_report = False # Dashboard becomes the html report
599+
sb_config._saved_dashboard_pie = None # Copy of pie chart for html report
600+
sb_config._dash_final_summary = None # Dash status to add to html report
601+
sb_config._html_report_name = None # The name of the pytest html report
597602

598603
arg_join = " ".join(sys.argv)
599604
if ("-n" in sys.argv) or ("-n=" in arg_join):
600605
sb_config._multithreaded = True
606+
if ("--html" in sys.argv or "--html=" in arg_join):
607+
sb_config._using_html_report = True
608+
sb_config._html_report_name = config.getoption("htmlpath")
609+
if sb_config.dashboard:
610+
if sb_config._html_report_name == "dashboard.html":
611+
sb_config._dash_is_html_report = True
601612

602613
if "linux" in sys.platform and (
603614
not sb_config.headed and not sb_config.headless):
@@ -654,10 +665,16 @@ def pytest_runtest_setup():
654665
if not sb_config.item_count_finalized:
655666
sb_config.item_count_finalized = True
656667
sb_config.item_count_untested = sb_config.item_count
657-
dashboard_html = "file://" + os.getcwd() + "/dashboard.html"
668+
dashboard_html = os.getcwd() + "/dashboard.html"
658669
star_len = len("Dashboard: ") + len(dashboard_html)
659670
stars = "*" * star_len
660-
print("\nDashboard: %s\n%s" % (dashboard_html, stars))
671+
colorama.init(autoreset=True)
672+
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
673+
cr = colorama.Style.RESET_ALL
674+
if "linux" in sys.platform:
675+
c1 = ''
676+
cr = ''
677+
print("\nDashboard: %s%s%s\n%s" % (c1, dashboard_html, cr, stars))
661678

662679

663680
def pytest_runtest_teardown(item):
@@ -687,6 +704,20 @@ def pytest_sessionfinish(session):
687704
pass
688705

689706

707+
def pytest_terminal_summary(terminalreporter):
708+
if sb_config._has_exception and (
709+
sb_config.dashboard and not sb_config._only_unittest):
710+
# Print link a second time because the first one may be off-screen
711+
dashboard_file = os.getcwd() + "/dashboard.html"
712+
terminalreporter.write_sep(
713+
"-", "Dashboard: %s" % dashboard_file)
714+
if sb_config._has_exception or sb_config.save_screenshot:
715+
# Log files are generated during test failures and Screenshot Mode
716+
latest_logs_dir = os.getcwd() + "/latest_logs/"
717+
terminalreporter.write_sep(
718+
"-", "LogPath: %s" % latest_logs_dir)
719+
720+
690721
def pytest_unconfigure():
691722
""" This runs after all tests have completed with pytest. """
692723
proxy_helper.remove_proxy_zip_if_present()
@@ -702,12 +733,20 @@ def pytest_unconfigure():
702733
sb_config.shared_driver = None
703734
log_helper.archive_logs_if_set(sb_config.log_path, sb_config.archive_logs)
704735

705-
# Dashboard post-processing: Disable auto-refresh and stamp complete
736+
# Dashboard post-processing: Disable time-based refresh and stamp complete
706737
if sb_config.dashboard and not sb_config._only_unittest:
707-
stamp = "\n<!--Test Run Complete-->"
738+
stamp = ""
739+
if sb_config._dash_is_html_report:
740+
# (If the Dashboard URL is the same as the HTML Report URL:)
741+
# Have the html report refresh back to a dashboard on update
742+
stamp += (
743+
'\n<script type="text/javascript" src="%s">'
744+
'</script>' % constants.Dashboard.LIVE_JS)
745+
stamp += "\n<!--Test Run Complete-->"
708746
find_it = constants.Dashboard.META_REFRESH_HTML
709747
swap_with = '' # Stop refreshing the page after the run is done
710748
try:
749+
# Part 1: Finalizing the dashboard / integrating html report
711750
time.sleep(0.3) # Add time for "livejs" to detect changes
712751
abs_path = os.path.abspath('.')
713752
dashboard_path = os.path.join(abs_path, "dashboard.html")
@@ -717,27 +756,43 @@ def pytest_unconfigure():
717756
# If the test run doesn't complete by itself, stop refresh
718757
the_html = the_html.replace(find_it, swap_with)
719758
the_html += stamp
759+
if sb_config._dash_is_html_report and (
760+
sb_config._saved_dashboard_pie):
761+
the_html = the_html.replace(
762+
"<h1>dashboard.html</h1>",
763+
sb_config._saved_dashboard_pie)
764+
the_html = the_html.replace(
765+
"</head>", '</head><link rel="shortcut icon" '
766+
'href="https://seleniumbase.io/img/dash_pie_2.png">')
767+
if sb_config._dash_final_summary:
768+
the_html += sb_config._dash_final_summary
720769
time.sleep(0.25)
721770
with open(dashboard_path, "w", encoding='utf-8') as f:
722771
f.write(the_html)
772+
# Part 2: Appending a pytest html report with dashboard data
773+
html_report_path = os.path.join(
774+
abs_path, sb_config._html_report_name)
775+
if sb_config._using_html_report and (
776+
os.path.exists(html_report_path) and
777+
not sb_config._dash_is_html_report):
778+
# Add the dashboard pie to the pytest html report
779+
with open(html_report_path, 'r', encoding='utf-8') as f:
780+
the_html = f.read()
781+
if sb_config._saved_dashboard_pie:
782+
the_html = the_html.replace(
783+
"<h1>%s</h1>" % sb_config._html_report_name,
784+
sb_config._saved_dashboard_pie)
785+
the_html = the_html.replace(
786+
"</head>", '</head><link rel="shortcut icon" '
787+
'href="https://seleniumbase.io/img/dash_pie_2.png">')
788+
if sb_config._dash_final_summary:
789+
the_html += sb_config._dash_final_summary
790+
with open(html_report_path, "w", encoding='utf-8') as f:
791+
f.write(the_html)
723792
except Exception:
724793
pass
725794

726795

727-
def pytest_terminal_summary(terminalreporter):
728-
if sb_config._has_exception and (
729-
sb_config.dashboard and not sb_config._only_unittest):
730-
# Print link a second time because the first one may be off-screen
731-
dashboard_file = "file://" + os.getcwd() + "/dashboard.html"
732-
terminalreporter.write_sep(
733-
"-", "Dashboard: %s" % dashboard_file)
734-
if sb_config._has_exception or sb_config.save_screenshot:
735-
# Log files are generated during test failures and Screenshot Mode
736-
latest_logs_dir = os.getcwd() + "/latest_logs/"
737-
terminalreporter.write_sep(
738-
"-", "Log files: %s" % latest_logs_dir)
739-
740-
741796
@pytest.fixture()
742797
def sb(request):
743798
""" SeleniumBase as a pytest fixture.
@@ -827,5 +882,12 @@ def pytest_runtest_makereport(item, call):
827882
extra = getattr(report, 'extra', [])
828883
if len(extra_report) > 1 and extra_report[1]["content"]:
829884
report.extra = extra + extra_report
885+
if sb_config._dash_is_html_report:
886+
# (If the Dashboard URL is the same as the HTML Report URL:)
887+
# Have the html report refresh back to a dashboard on update
888+
refresh_updates = (
889+
'<script type="text/javascript" src="%s">'
890+
'</script>' % constants.Dashboard.LIVE_JS)
891+
report.extra.append(pytest_html.extras.html(refresh_updates))
830892
except Exception:
831893
pass

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@
176176
'Pillow==6.2.2;python_version<"3.5"',
177177
'Pillow==7.2.0;python_version>="3.5" and python_version<"3.6"',
178178
'Pillow==8.0.1;python_version>="3.6"',
179-
'rich==9.4.0;python_version>="3.6" and python_version<"4.0"',
179+
'rich==9.5.1;python_version>="3.6" and python_version<"4.0"',
180180
'zipp==1.2.0;python_version<"3.6"',
181181
'zipp==3.4.0;python_version>="3.6"',
182182
'flake8==3.7.9;python_version<"3.5"',

0 commit comments

Comments
 (0)