Skip to content

Commit a19a63c

Browse files
committed
Add save_teardown_screenshot() and refactor BaseCase
1 parent 2910722 commit a19a63c

File tree

1 file changed

+78
-70
lines changed

1 file changed

+78
-70
lines changed

seleniumbase/fixtures/base_case.py

Lines changed: 78 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def __init__(self, *args, **kwargs):
7878
self.__last_page_load_url = "data:,"
7979
self.__last_page_screenshot = None
8080
self.__last_page_screenshot_png = None
81+
self.__added_pytest_html_extra = None
8182
self.__delayed_assert_count = 0
8283
self.__delayed_assert_failures = []
8384
self.__device_width = None
@@ -4110,9 +4111,7 @@ def setUp(self, masterqa_mode=False):
41104111
self.is_pytest = False
41114112
if self.is_pytest:
41124113
# pytest-specific code
4113-
test_id = "%s.%s.%s" % (self.__class__.__module__,
4114-
self.__class__.__name__,
4115-
self._testMethodName)
4114+
test_id = self.__get_test_id()
41164115
self.browser = sb_config.browser
41174116
self.data = sb_config.data
41184117
self.slow_mode = sb_config.slow_mode
@@ -4218,10 +4217,10 @@ def setUp(self, masterqa_mode=False):
42184217

42194218
# Verify that SeleniumBase is installed successfully
42204219
if not hasattr(self, "browser"):
4221-
raise Exception("""SeleniumBase plugins did not load! """
4222-
"""Please reinstall using:\n"""
4223-
""" >>> "pip install -r requirements.txt" <<<\n"""
4224-
""" >>> "python setup.py install" <<< """)
4220+
raise Exception("""SeleniumBase plugins DID NOT load!\n\n"""
4221+
"""*** Please REINSTALL SeleniumBase using: >\n"""
4222+
""" >>> "pip install -r requirements.txt"\n"""
4223+
""" >>> "python setup.py install" """)
42254224
if self.settings_file:
42264225
settings_parser.set_settings(self.settings_file)
42274226
# Mobile Emulator device metrics: CSS Width, CSS Height, & Pixel-Ratio
@@ -4348,27 +4347,29 @@ def __insert_test_result(self, state, err):
43484347
self.testcase_manager.update_testcase_data(data_payload)
43494348

43504349
def __add_pytest_html_extra(self):
4351-
try:
4352-
if self.with_selenium:
4353-
if not self.__last_page_screenshot:
4354-
self.__set_last_page_screenshot()
4355-
if self.report_on:
4356-
extra_url = {}
4357-
extra_url['name'] = 'URL'
4358-
extra_url['format'] = 'url'
4359-
extra_url['content'] = self.get_current_url()
4360-
extra_url['mime_type'] = None
4361-
extra_url['extension'] = None
4362-
extra_image = {}
4363-
extra_image['name'] = 'Screenshot'
4364-
extra_image['format'] = 'image'
4365-
extra_image['content'] = self.__last_page_screenshot
4366-
extra_image['mime_type'] = 'image/png'
4367-
extra_image['extension'] = 'png'
4368-
self._html_report_extra.append(extra_url)
4369-
self._html_report_extra.append(extra_image)
4370-
except Exception:
4371-
pass
4350+
if not self.__added_pytest_html_extra:
4351+
try:
4352+
if self.with_selenium:
4353+
if not self.__last_page_screenshot:
4354+
self.__set_last_page_screenshot()
4355+
if self.report_on:
4356+
extra_url = {}
4357+
extra_url['name'] = 'URL'
4358+
extra_url['format'] = 'url'
4359+
extra_url['content'] = self.get_current_url()
4360+
extra_url['mime_type'] = None
4361+
extra_url['extension'] = None
4362+
extra_image = {}
4363+
extra_image['name'] = 'Screenshot'
4364+
extra_image['format'] = 'image'
4365+
extra_image['content'] = self.__last_page_screenshot
4366+
extra_image['mime_type'] = 'image/png'
4367+
extra_image['extension'] = 'png'
4368+
self.__added_pytest_html_extra = True
4369+
self._html_report_extra.append(extra_url)
4370+
self._html_report_extra.append(extra_image)
4371+
except Exception:
4372+
pass
43724373

43734374
def __quit_all_drivers(self):
43744375
if self._reuse_session and sb_config.shared_driver:
@@ -4394,19 +4395,55 @@ def __quit_all_drivers(self):
43944395
self._default_driver = None
43954396
self._drivers_list = []
43964397

4398+
def __has_exception(self):
4399+
has_exception = False
4400+
if sys.version_info[0] >= 3 and hasattr(self, '_outcome'):
4401+
if hasattr(self._outcome, 'errors') and self._outcome.errors:
4402+
has_exception = True
4403+
else:
4404+
has_exception = sys.exc_info()[1] is not None
4405+
return has_exception
4406+
4407+
def __get_test_id(self):
4408+
test_id = "%s.%s.%s" % (self.__class__.__module__,
4409+
self.__class__.__name__,
4410+
self._testMethodName)
4411+
return test_id
4412+
4413+
def __create_log_path_as_needed(self, test_logpath):
4414+
if not os.path.exists(test_logpath):
4415+
try:
4416+
os.makedirs(test_logpath)
4417+
except Exception:
4418+
pass # Only reachable during multi-threaded runs
4419+
4420+
def save_teardown_screenshot(self):
4421+
""" (Should ONLY be used at the start of custom tearDown() methods.)
4422+
This method takes a screenshot of the current web page for a
4423+
failing test (or when running your tests with --save-screenshot).
4424+
That way your tearDown() method can navigate away from the last
4425+
page where the test failed, and still get the correct screenshot
4426+
before performing tearDown() steps on other pages. If this method
4427+
is not included in your custom tearDown() method, a screenshot
4428+
will still be taken after the last step of your tearDown(), where
4429+
you should be calling "super(SubClassOfBaseCase, self).tearDown()"
4430+
"""
4431+
test_id = self.__get_test_id()
4432+
test_logpath = self.log_path + "/" + test_id
4433+
self.__create_log_path_as_needed(test_logpath)
4434+
if self.__has_exception() or self.save_screenshot_after_test:
4435+
self.__set_last_page_screenshot()
4436+
if self.is_pytest:
4437+
self.__add_pytest_html_extra()
4438+
43974439
def tearDown(self):
43984440
"""
43994441
Be careful if a subclass of BaseCase overrides setUp()
44004442
You'll need to add the following line to the subclass's tearDown():
44014443
super(SubClassOfBaseCase, self).tearDown()
44024444
"""
44034445
self.__slow_mode_pause_if_active()
4404-
has_exception = False
4405-
if sys.version_info[0] >= 3 and hasattr(self, '_outcome'):
4406-
if hasattr(self._outcome, 'errors') and self._outcome.errors:
4407-
has_exception = True
4408-
else:
4409-
has_exception = sys.exc_info()[1] is not None
4446+
has_exception = self.__has_exception()
44104447
if self.__delayed_assert_failures:
44114448
print(
44124449
"\nWhen using self.delayed_assert_*() methods in your tests, "
@@ -4416,18 +4453,9 @@ def tearDown(self):
44164453
self.process_delayed_asserts()
44174454
else:
44184455
self.process_delayed_asserts(print_only=True)
4419-
self.is_pytest = None
4420-
try:
4421-
# This raises an exception if the test is not coming from pytest
4422-
self.is_pytest = sb_config.is_pytest
4423-
except Exception:
4424-
# Not using pytest (probably nosetests)
4425-
self.is_pytest = False
44264456
if self.is_pytest:
44274457
# pytest-specific code
4428-
test_id = "%s.%s.%s" % (self.__class__.__module__,
4429-
self.__class__.__name__,
4430-
self._testMethodName)
4458+
test_id = self.__get_test_id()
44314459
try:
44324460
with_selenium = self.with_selenium
44334461
except Exception:
@@ -4462,11 +4490,7 @@ def tearDown(self):
44624490
if self.with_testing_base and not has_exception and (
44634491
self.save_screenshot_after_test):
44644492
test_logpath = self.log_path + "/" + test_id
4465-
if not os.path.exists(test_logpath):
4466-
try:
4467-
os.makedirs(test_logpath)
4468-
except Exception:
4469-
pass # Only reachable during multi-threaded runs
4493+
self.__create_log_path_as_needed(test_logpath)
44704494
if not self.__last_page_screenshot_png:
44714495
self.__set_last_page_screenshot()
44724496
log_helper.log_screenshot(
@@ -4476,11 +4500,7 @@ def tearDown(self):
44764500
self.__add_pytest_html_extra()
44774501
if self.with_testing_base and has_exception:
44784502
test_logpath = self.log_path + "/" + test_id
4479-
if not os.path.exists(test_logpath):
4480-
try:
4481-
os.makedirs(test_logpath)
4482-
except Exception:
4483-
pass # Only reachable during multi-threaded runs
4503+
self.__create_log_path_as_needed(test_logpath)
44844504
if ((not self.with_screen_shots) and (
44854505
not self.with_basic_test_info) and (
44864506
not self.with_page_source)):
@@ -4555,15 +4575,9 @@ def tearDown(self):
45554575
else:
45564576
# (Nosetests)
45574577
if has_exception:
4558-
test_id = "%s.%s.%s" % (self.__class__.__module__,
4559-
self.__class__.__name__,
4560-
self._testMethodName)
4578+
test_id = self.__get_test_id()
45614579
test_logpath = self.log_path + "/" + test_id
4562-
if not os.path.exists(test_logpath):
4563-
try:
4564-
os.makedirs(test_logpath)
4565-
except Exception:
4566-
pass # Only reachable during multi-threaded runs
4580+
self.__create_log_path_as_needed(test_logpath)
45674581
log_helper.log_test_failure_data(
45684582
self, test_logpath, self.driver, self.browser)
45694583
if len(self._drivers_list) > 0:
@@ -4575,15 +4589,9 @@ def tearDown(self):
45754589
self.__last_page_screenshot_png)
45764590
log_helper.log_page_source(test_logpath, self.driver)
45774591
elif self.save_screenshot_after_test:
4578-
test_id = "%s.%s.%s" % (self.__class__.__module__,
4579-
self.__class__.__name__,
4580-
self._testMethodName)
4592+
test_id = self.__get_test_id()
45814593
test_logpath = self.log_path + "/" + test_id
4582-
if not os.path.exists(test_logpath):
4583-
try:
4584-
os.makedirs(test_logpath)
4585-
except Exception:
4586-
pass # Only reachable during multi-threaded runs
4594+
self.__create_log_path_as_needed(test_logpath)
45874595
if not self.__last_page_screenshot_png:
45884596
self.__set_last_page_screenshot()
45894597
log_helper.log_screenshot(

0 commit comments

Comments
 (0)