def pytest_runtest_makereport(item, call): pytest_html = item.config.pluginmanager.getplugin('html') outcome = yield report = outcome.get_result() extra = getattr(report, 'extra', []) if report.when in ('call', 'setup'): xfail = hasattr(report, 'wasxfail') if ((report.passed or report.skipped) and xfail) or (report.failed and not xfail): # only add additional html on failure try: if type(factory.get_shared_driver()) is not NoneObject: screen = take_screenshot( webdriver=factory.get_shared_driver(), filename=item.function.__name__) extra.append(pytest_html.extras.image(screen)) allure.attach.file(screen, item.function.__name__, allure.attachment_type.PNG) except Exception as e: print(f"Could not create a screenshot:\n{e}") if xfail: extra.append( pytest_html.extras.html( '<div style="color: orange">XFailed reason: {}</div><br />' .format(report.wasxfail))) report.extra = extra
def take_screenshot(path=None, filename=None): if not path: path = selene.config.reports_folder if not filename: filename = "screen_{id}".format(id=next(selene.config.counter)) screenshot_path = helpers.take_screenshot(driver(), path, filename) global _latest_screenshot _latest_screenshot = screenshot_path return screenshot_path
def _wait_with_screenshot(webdriver, entity, condition, timeout=None, polling=None): if timeout is None: timeout = config.timeout if polling is None: polling = config.poll_during_waits try: return wait_for(entity, condition, timeout, polling) except TimeoutException as e: screenshot = helpers.take_screenshot(webdriver, ) msg = '''{original_msg} screenshot: file://{screenshot}'''.format(original_msg=e.msg, screenshot=screenshot) raise TimeoutException(msg, e.screen, e.stacktrace)
def screenshot(name, path='./'): return take_screenshot(browser(), name, path)
def wait_for(code=lambda: None, until=lambda code_result: code_result.is_displayed(), by_demand_after=lambda: None, wait_time=config.default_wait_time): """ waits `wait_time` smartly for the `until` conditions to be satisfied on the result of executing `code` but after the `after` code was executed optionally in case code() gave no satisfied result at first attempt :param code - in case hasattr(code, 'to_str') to_str() method will be called to stringify code at error message in case of failed wait_for """ # todo: think on: better name for by_demand_after, or even another way to implement this feature # todo: think on: letting the wait_for to accept hamcrest matchers as 'until' conditions # todo: think on: renaming 'code' param to element_finder in case wait_for will be only "element wait" implementation. # the `code` name was chosen in order to implement "general case" of waiter # nevertheless, the wait_for implementation has some parts bounded to the "element finding" context, # like throwing specific exception in case element was not found... conditions = until if isinstance(until, (tuple, list)) else [until] import stopit import time # todo: catch 'all' possible relevant exceptions below... # todo: it was assumed that after() will not be needed once exception was encountered... Though this needs to be proved... # todo: and documented result = DummyResult() with suppress(StaleElementReferenceException, NoSuchElementException, CannotSendRequest): result = code() if conditions and not satisfied(result, *conditions): by_demand_after() # todo: think on: refactoring to match at once the result to all conditions combined into one # since it will check conditions one by one, one after another... and in the final end, some previous # conditions may not be met already... for condition_met in conditions: with stopit.ThreadingTimeout(wait_time) as to_ctx_mgr: while not condition_met(result): with suppress(StaleElementReferenceException, NoSuchElementException, CannotSendRequest): time.sleep(0.1) result = code() if not to_ctx_mgr: # todo: think on: refactor the following code, make it just `raise stopit.TimeoutException(repr(code))` or etc. # todo: make the following 'screenshot taking' code optional (controoled via config) # todo: think on: unbinding screenshooting from the wait_for implementation screenshot = '%s.png' % time.time() path = os.path.abspath('./reports/screenshots') # todo: make screenshots path configurable full_path = take_screenshot(browser(), screenshot, path) err_message = """ Timeout reached while waiting... During: %ss For: %s Until: %s Screenshot: %s """ % (wait_time, code.__name__, # todo: think on: refactoring to the usage without "underscores" condition_met.__name__, full_path) raise stopit.TimeoutException(err_message) # todo: improve error message. Also taking into account the proper alternative of condition implementation # e.g. as hamcrest matchers return result
def wait_for(code=lambda: None, until=lambda code_result: code_result.is_displayed(), by_demand_after=lambda: None, wait_time=config.default_wait_time): """ waits `wait_time` smartly for the `until` conditions to be satisfied on the result of executing `code` but after the `after` code was executed optionally in case code() gave no satisfied result at first attempt :param code - in case hasattr(code, 'to_str') to_str() method will be called to stringify code at error message in case of failed wait_for """ # todo: think on: better name for by_demand_after, or even another way to implement this feature # todo: think on: letting the wait_for to accept hamcrest matchers as 'until' conditions # todo: think on: renaming 'code' param to element_finder in case wait_for will be only "element wait" implementation. # the `code` name was chosen in order to implement "general case" of waiter # nevertheless, the wait_for implementation has some parts bounded to the "element finding" context, # like throwing specific exception in case element was not found... conditions = until if isinstance(until, (tuple, list)) else [until] import stopit import time # todo: catch 'all' possible relevant exceptions below... # todo: it was assumed that after() will not be needed once exception was encountered... Though this needs to be proved... # todo: and documented result = DummyResult() with suppress(StaleElementReferenceException, NoSuchElementException, CannotSendRequest): result = code() if conditions and not satisfied(result, *conditions): by_demand_after() # todo: think on: refactoring to match at once the result to all conditions combined into one # since it will check conditions one by one, one after another... and in the final end, some previous # conditions may not be met already... for condition_met in conditions: with stopit.ThreadingTimeout(wait_time) as to_ctx_mgr: while not condition_met(result): with suppress(StaleElementReferenceException, NoSuchElementException, CannotSendRequest): time.sleep(0.1) result = code() if not to_ctx_mgr: # todo: think on: refactor the following code, make it just `raise stopit.TimeoutException(repr(code))` or etc. # todo: make the following 'screenshot taking' code optional (controoled via config) # todo: think on: unbinding screenshooting from the wait_for implementation screenshot = '%s.png' % time.time() path = os.path.abspath( './reports/screenshots' ) # todo: make screenshots path configurable full_path = take_screenshot(browser(), screenshot, path) err_message = """ Timeout reached while waiting... During: %ss For: %s Until: %s Screenshot: %s """ % ( wait_time, code. __name__, # todo: think on: refactoring to the usage without "underscores" condition_met.__name__, full_path) raise stopit.TimeoutException(err_message) # todo: improve error message. Also taking into account the proper alternative of condition implementation # e.g. as hamcrest matchers return result
def screenshot(name=_picture_name(), path=settings.screenshot_path): return take_screenshot(browser(), name, path)