Skip to content

Commit 3baf9fe

Browse files
committed
Make logging improvements to the sb pytest fixture
1 parent b07e065 commit 3baf9fe

File tree

3 files changed

+87
-21
lines changed

3 files changed

+87
-21
lines changed

seleniumbase/core/log_helper.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,41 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
3737
data_to_save.append("Last Page: %s" % last_page)
3838
data_to_save.append(" Browser: %s" % browser)
3939
data_to_save.append("Timestamp: %s" % int(time.time()))
40-
if sys.version_info[0] >= 3 and hasattr(test, '_outcome'):
41-
if test._outcome.errors:
42-
try:
43-
exc_message = test._outcome.errors[0][1][1]
44-
traceback_address = test._outcome.errors[0][1][2]
45-
traceback_list = traceback.format_list(
46-
traceback.extract_tb(traceback_address)[1:])
47-
traceback_message = ''.join(traceback_list).strip()
48-
except Exception:
49-
exc_message = "(Unknown Exception)"
50-
traceback_message = "(Unknown Traceback)"
51-
data_to_save.append("Traceback: " + traceback_message)
52-
data_to_save.append("Exception: " + str(exc_message))
40+
if sys.version_info[0] >= 3 and hasattr(test, '_outcome') and (
41+
hasattr(test._outcome, 'errors') and test._outcome.errors):
42+
try:
43+
exc_message = test._outcome.errors[0][1][1]
44+
traceback_address = test._outcome.errors[0][1][2]
45+
traceback_list = traceback.format_list(
46+
traceback.extract_tb(traceback_address)[1:])
47+
traceback_message = ''.join(traceback_list).strip()
48+
except Exception:
49+
exc_message = "(Unknown Exception)"
50+
traceback_message = "(Unknown Traceback)"
51+
data_to_save.append("Traceback: " + traceback_message)
52+
data_to_save.append("Exception: " + str(exc_message))
5353
else:
54-
data_to_save.append("Traceback: " + ''.join(
54+
the_traceback = None
55+
the_traceback = ''.join(
5556
traceback.format_exception(sys.exc_info()[0],
5657
sys.exc_info()[1],
57-
sys.exc_info()[2])))
58+
sys.exc_info()[2]))
59+
if not the_traceback or len(str(the_traceback)) < 30 or (
60+
the_traceback.endswith("StopIteration\n")):
61+
good_stack = []
62+
the_stacks = traceback.format_list(
63+
traceback.extract_tb(sys.last_traceback))
64+
for stack in the_stacks:
65+
if "/site-packages/pluggy/" not in stack:
66+
if "/site-packages/_pytest/" not in stack:
67+
good_stack.append(stack)
68+
the_traceback = ''.join(good_stack)
69+
data_to_save.append("Traceback: " + the_traceback)
70+
last_value = sys.last_value
71+
if last_value:
72+
data_to_save.append("Exception: " + str(last_value))
73+
else:
74+
data_to_save.append("Traceback: " + the_traceback)
5875
log_file.writelines("\r\n".join(data_to_save))
5976
log_file.close()
6077

seleniumbase/fixtures/base_case.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def __init__(self, *args, **kwargs):
8484
self._language = "English"
8585
self._presentation_slides = {}
8686
self._presentation_transition = {}
87+
self._sb_test_identifier = None
8788
self._html_report_extra = [] # (Used by pytest_plugin.py)
8889
self._default_driver = None
8990
self._drivers_list = []
@@ -6315,7 +6316,9 @@ def __quit_all_drivers(self):
63156316

63166317
def __has_exception(self):
63176318
has_exception = False
6318-
if sys.version_info[0] >= 3 and hasattr(self, '_outcome'):
6319+
if hasattr(sys, 'last_traceback') and sys.last_traceback is not None:
6320+
has_exception = True
6321+
elif sys.version_info[0] >= 3 and hasattr(self, '_outcome'):
63196322
if hasattr(self._outcome, 'errors') and self._outcome.errors:
63206323
has_exception = True
63216324
else:
@@ -6326,6 +6329,8 @@ def __get_test_id(self):
63266329
test_id = "%s.%s.%s" % (self.__class__.__module__,
63276330
self.__class__.__name__,
63286331
self._testMethodName)
6332+
if self._sb_test_identifier and len(str(self._sb_test_identifier)) > 6:
6333+
test_id = self._sb_test_identifier
63296334
return test_id
63306335

63316336
def __create_log_path_as_needed(self, test_logpath):

seleniumbase/plugins/pytest_plugin.py

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ def pytest_configure(config):
520520
sb_config.visual_baseline = config.getoption('visual_baseline')
521521
sb_config.timeout_multiplier = config.getoption('timeout_multiplier')
522522
sb_config.pytest_html_report = config.getoption('htmlpath') # --html=FILE
523+
sb_config._sb_node = {} # sb node dictionary (Used with the sb fixture)
523524

524525
if sb_config.reuse_session:
525526
arg_join = " ".join(sys.argv)
@@ -592,19 +593,35 @@ def sb(request):
592593
from seleniumbase import BaseCase
593594

594595
class BaseClass(BaseCase):
595-
def base_method():
596+
597+
def setUp(self):
598+
super(BaseClass, self).setUp()
599+
600+
def tearDown(self):
601+
self.save_teardown_screenshot()
602+
super(BaseClass, self).tearDown()
603+
604+
def base_method(self):
596605
pass
597606

598607
if request.cls:
599608
request.cls.sb = BaseClass("base_method")
600609
request.cls.sb.setUp()
610+
request.cls.sb._needs_tearDown = True
611+
sb_config._sb_node[request.node.nodeid] = request.cls.sb
601612
yield request.cls.sb
602-
request.cls.sb.tearDown()
613+
if request.cls.sb._needs_tearDown:
614+
request.cls.sb.tearDown()
615+
request.cls.sb._needs_tearDown = False
603616
else:
604617
sb = BaseClass("base_method")
605618
sb.setUp()
619+
sb._needs_tearDown = True
620+
sb_config._sb_node[request.node.nodeid] = sb
606621
yield sb
607-
sb.tearDown()
622+
if sb._needs_tearDown:
623+
sb.tearDown()
624+
sb._needs_tearDown = False
608625

609626

610627
@pytest.mark.hookwrapper
@@ -614,9 +631,36 @@ def pytest_runtest_makereport(item, call):
614631
report = outcome.get_result()
615632
if pytest_html and report.when == 'call':
616633
try:
617-
extra_report = item._testcase._html_report_extra
634+
extra_report = None
635+
if hasattr(item, "_testcase"):
636+
extra_report = item._testcase._html_report_extra
637+
elif hasattr(item.instance, "sb") or (
638+
item.nodeid in sb_config._sb_node):
639+
if not hasattr(item.instance, "sb"):
640+
sb_node = sb_config._sb_node[item.nodeid]
641+
else:
642+
sb_node = item.instance.sb
643+
test_id = item.nodeid
644+
if not test_id:
645+
test_id = "unidentified_TestCase"
646+
test_id = test_id.replace(' ', '_')
647+
if '[' in test_id:
648+
import re
649+
test_id_intro = test_id.split('[')[0]
650+
parameter = test_id.split('[')[1]
651+
parameter = re.sub(re.compile(r'\W'), '', parameter)
652+
test_id = test_id_intro + "__" + parameter
653+
test_id = test_id.replace('/', '.').replace('\\', '.')
654+
test_id = test_id.replace('::', '.').replace('.py', '')
655+
sb_node._sb_test_identifier = test_id
656+
if sb_node._needs_tearDown:
657+
sb_node.tearDown()
658+
sb_node._needs_tearDown = False
659+
extra_report = sb_node._html_report_extra
660+
else:
661+
return
618662
extra = getattr(report, 'extra', [])
619-
if extra_report[1]["content"]:
663+
if len(extra_report) > 1 and extra_report[1]["content"]:
620664
report.extra = extra + extra_report
621665
except Exception:
622666
pass

0 commit comments

Comments
 (0)