Source code for webdriverwrapper.unittest.testcase

# pylint: disable=all

import logging
logging.basicConfig(level=logging.INFO)
import unittest
import sys

import webdriverwrapper.exceptions as exceptions
from webdriverwrapper.wrapper import Firefox, Chrome, ChromeOptions

__all__ = (
    'WebdriverTestCase',
    'ONE_INSTANCE_FOR_ALL_TESTS',
    'ONE_INSTANCE_PER_TESTCASE',
    'ONE_INSTANCE_PER_TEST',
)


ONE_INSTANCE_FOR_ALL_TESTS = 0
ONE_INSTANCE_PER_TESTCASE = 1
ONE_INSTANCE_PER_TEST = 2


[docs]class WebdriverTestCase(unittest.TestCase): """ Base ``TestCase`` used for testing with :py:mod:`unittest`. Example: .. code-block:: python class TestCase(webdriverwrapper.unittest.WebdriverTestCase): domain = 'www.google.com' instances_of_driver = webdriverwrapper.unittest.ONE_INSTANCE_PER_TESTCASE screenshot_path = os.path.join('/', 'tmp', 'testreport') def _get_driver(self): return Chrome() def test_doodle(self): self.click('gbqfsb') self.assertTrue(self.contains_text('Doodles')) def test_search(self): self.get_elm('gbqf').fill_out_and_submit({ 'q': 'hello', }) self.wait_for_element(id_='resultStats') """ domain = None """ If you want working relative :py:meth:`go_to <webdriverwrapper.wrapper._WebdriverWrapper.go_to>` without having to call for first time :py:meth:`get <selenium.webdriver.remote.webdriver.WebDriver.get>` (because before that you can't use relative path), set this attribute. """ instances_of_driver = ONE_INSTANCE_FOR_ALL_TESTS """ Specify when you want to create *fresh* driver. By default there is one driver for all tests (:py:attr:`.ONE_INSTANCE_FOR_ALL_TESTS`) and you have to close it by yourself by calling :py:meth:`.quit_driver`. If you need clear cookies, local storage and everything, then consider to use new driver for every ``TestCase`` or even every test method. """ wait_after_test = False """ For debug only. When you set to ``True``, it will wait for pressing enter after each test before moving to next test. Ideal when you need to check out for example Chrome console. But maybe better debuging is with :py:meth:`.break_point`. """ screenshot_path = '' """ When you set this path, it will make automatically screenshots of failed tests and saved them to this path. """ def __init__(self, *args, **kwds): super(WebdriverTestCase, self).__init__(*args, **kwds) self.__class__._number_of_test = 0 self.__class__._count_of_tests = len([m for m in dir(self) if m.startswith('test')]) self.init() def init(self): pass def run(self, result=None): if result is None: result = self.defaultTestResult() result.startTest(self) test_method = getattr(self, self._testMethodName) self._test_method = test_method try: ok = False self._set_up() try: self.setUp() except KeyboardInterrupt: raise except: result.addError(self, sys.exc_info()) # setUp can fail because of app in some state returns internal #+ server error. It's good to know about it - it can say more #+ than that some element couldn't be found. try: self.driver.check_expected_errors(test_method) self.driver.check_expected_infos(test_method) except: result.addError(self, sys.exc_info()) return try: test_method() ok = True except self.failureException: self.make_screenshot() result.addFailure(self, sys.exc_info()) except KeyboardInterrupt: raise except: self.make_screenshot() result.addError(self, sys.exc_info()) try: self.driver.check_expected_errors(test_method) self.driver.check_expected_infos(test_method) except: ok = False result.addError(self, sys.exc_info()) try: self.tearDown() except KeyboardInterrupt: raise except: result.addError(self, sys.exc_info()) ok = False if ok: result.addSuccess(self) finally: if not ok: self.make_screenshot() result.stopTest(self) # Is nice to see at break point if test passed or not. # So this call have to be after stopTest which print result of test. self._tear_down()
[docs] def make_screenshot(self, screenshot_name=None): """ Save screenshot to :py:attr:`.screenshot_path` with given name ``screenshot_name``. If name is not given, then the name is name of current test (``self.id()``). .. versionchanged:: 2.2 Use ``make_screenshot`` directly on ``driver`` instead. This method is used for making screenshot of failed tests and therefor does nothing if ``screenshot_path`` is not configured. It stays there only for compatibility. """ if not screenshot_name: # Without name (and possibly path) we cannot make screenshot. Don't # know where to store it. if not self.screenshot_path: return screenshot_name = self.id() # Close unexpected alerts (it's blocking and then tests fails completely). self.driver.close_alert(ignore_exception=True) self.driver.get_screenshot_as_file('%s/%s.png' % (self.screenshot_path, screenshot_name))
def _set_up(self): self.__class__._number_of_test += 1 if not hasattr(WebdriverTestCase, 'driver'): WebdriverTestCase.driver = self._get_driver() WebdriverTestCase.screenshot_path = self.screenshot_path WebdriverTestCase._main_window = WebdriverTestCase.driver.current_window_handle if self.domain: WebdriverTestCase.driver.get(self.domain) # Ensure that test starts in main window. if self.driver.current_window_handle != self._main_window: self.driver.switch_to_window(self._main_window)
[docs] def _get_driver(self): """ Create driver. By default it creates Firefox. Change it to your needs. """ return Firefox()
def _tear_down(self): if self.wait_after_test: self.break_point() if self.instances_of_driver == ONE_INSTANCE_PER_TEST or ( self.instances_of_driver == ONE_INSTANCE_PER_TESTCASE and self._number_of_test == self._count_of_tests ): self.quit_driver()
[docs] @staticmethod def quit_driver(): """ When you set :py:attr:`.instances_of_driver` to :py:attr:`.ONE_INSTANCE_FOR_ALL_TESTS` (which is default), then you have to quit driver by yourself by this method. """ if hasattr(WebdriverTestCase, 'driver'): WebdriverTestCase.driver.quit() del WebdriverTestCase.driver
[docs] def debug(self, msg): logging.info(msg)
### Aliases to driver.
[docs] def break_point(self): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.break_point`. """ self.driver.break_point()
[docs] def check_errors(self, expected_error_page=None, allowed_error_pages=[], expected_error_messages=[], allowed_error_messages=[]): """ Alias for :py:meth:`~webdriverwrapper.errors.WebdriverWrapperErrorMixin.check_errors`. .. versionchanged:: 2.0 Only alias. Code moved to wrapper so it could be used also by pytest. """ self.driver.check_errors(expected_error_page, allowed_error_pages, expected_error_messages, allowed_error_messages)
[docs] def find_element_by_text(self, text): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverBaseWrapper.find_element_by_text`. .. versionadded:: 2.0 """ return self.driver.find_element_by_text(text)
[docs] def find_elements_by_text(self, text): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverBaseWrapper.find_elements_by_text`. """ return self.driver.find_elements_by_text(text)
[docs] def contains_text(self, text): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverBaseWrapper.contains_text`. """ return self.driver.contains_text(text)
[docs] def get_elm(self, *args, **kwds): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverBaseWrapper.get_elm`. """ return self.driver.get_elm(*args, **kwds)
[docs] def get_elms(self, *args, **kwds): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverBaseWrapper.get_elms`. """ return self.driver.get_elms(*args, **kwds)
[docs] def click(self, *args, **kwds): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverBaseWrapper.click`. """ self.driver.click(*args, **kwds)
[docs] def wait_for_element(self, *args, **kwds): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.wait_for_element`. """ return self.driver.wait_for_element(*args, **kwds)
[docs] def wait(self, timeout=10): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.wait`. """ return self.driver.wait(timeout)
[docs] def go_to(self, *args, **kwds): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.go_to`. """ self.driver.go_to(*args, **kwds)
[docs] def switch_to_window(self, window_name=None, title=None, url=None): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.switch_to_window`. """ self.driver.switch_to_window(window_name, title, url)
[docs] def close_window(self, window_name=None, title=None, url=None): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.close_window`. """ self.driver.close_window(window_name, title, url)
[docs] def close_other_windows(self): """ Alias for :py:meth:`~webdriverwrapper.wrapper._WebdriverWrapper.close_other_windows`. """ self.driver.close_other_windows()