From b64cfce04d93716f1bd2dc498dd4986e7829c4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Gonz=C3=A1lez=20Alonso?= Date: Thu, 14 Apr 2016 18:04:14 +0200 Subject: [PATCH] Refactor WebElement mocks in unit tests --- docs/conf.py | 4 +- .../pageelements/test_derived_page_element.py | 35 ++++++--------- .../test/pageelements/test_page_element.py | 45 +++++++------------ .../test/pageelements/test_page_elements.py | 30 +++++-------- toolium/test/pageobjects/test_page_object.py | 11 ++--- toolium/test/test_config_driver.py | 6 +-- toolium/test/test_driver_wrapper.py | 7 ++- toolium/test/test_utils.py | 23 ++++++---- toolium/test/test_visual_test.py | 13 ++---- toolium/utils.py | 8 ++-- toolium/visual_test.py | 4 +- 11 files changed, 80 insertions(+), 106 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index fe1e1ede..5291471c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -77,12 +77,12 @@ # built documents. # # The short X.Y version. -version = file('../VERSION').read().strip() +version = open('../VERSION').read().strip() # The full version, including alpha/beta/rc tags. import subprocess git_log = subprocess.check_output(["git", "log", "--pretty=oneline"]) -commits = git_log.split('\n') +commits = git_log.split(b'\n') release = '{}-{}'.format(version, len(commits) - 1) # The language for content autogenerated by Sphinx. Refer to documentation diff --git a/toolium/test/pageelements/test_derived_page_element.py b/toolium/test/pageelements/test_derived_page_element.py index a33d3bb9..e7748da4 100644 --- a/toolium/test/pageelements/test_derived_page_element.py +++ b/toolium/test/pageelements/test_derived_page_element.py @@ -21,6 +21,7 @@ import mock from nose.tools import assert_equal from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webelement import WebElement from toolium.driver_wrapper import DriverWrapper from toolium.driver_wrappers_pool import DriverWrappersPool @@ -29,16 +30,6 @@ from toolium.pageobjects.page_object import PageObject child_element = 'child_element' -mock_element = None - - -@mock.patch('selenium.webdriver.remote.webelement.WebElement', spec=True) -def get_mock_element(WebElement): - web_element = WebElement.return_value - web_element.find_element.return_value = child_element - web_element.text = 'text value' - web_element.get_attribute.return_value = 'input text value' - return web_element def get_mock_select(): @@ -71,8 +62,11 @@ class LoginPageObject(PageObject): class TestDerivedPageElement(unittest.TestCase): def setUp(self): """Create a new mock element and a new driver before each test""" - global mock_element - mock_element = get_mock_element() + # Create a mock element + self.mock_element = mock.MagicMock(spec=WebElement) + self.mock_element.find_element.return_value = child_element + self.mock_element.text = 'text value' + self.mock_element.get_attribute.return_value = 'input text value' # Reset wrappers pool values DriverWrappersPool._empty_pool() @@ -97,14 +91,14 @@ def test_locator(self): assert_equal(page_object.menu.logo.parent, page_object.menu) def test_get_text(self): - self.driver_wrapper.driver.find_element.return_value = mock_element + self.driver_wrapper.driver.find_element.return_value = self.mock_element title_value = LoginPageObject().title.text assert_equal(title_value, 'text value') def test_get_input_text(self): - self.driver_wrapper.driver.find_element.return_value = mock_element + self.driver_wrapper.driver.find_element.return_value = self.mock_element username_value = LoginPageObject().username.text @@ -112,12 +106,12 @@ def test_get_input_text(self): def test_set_input_text(self): # Configure driver mock - self.driver_wrapper.driver.find_element.return_value = mock_element + self.driver_wrapper.driver.find_element.return_value = self.mock_element self.driver_wrapper.is_ios_test = mock.MagicMock(return_value=False) LoginPageObject().username.text = 'new input value' - assert_equal(mock_element.send_keys.mock_calls, [mock.call('new input value')]) + self.mock_element.send_keys.assert_called_with('new input value') def test_get_selected_option(self): select_page_element.SeleniumSelect = get_mock_select() @@ -131,12 +125,11 @@ def test_set_option(self): LoginPageObject().language.option = 'new option value' - assert_equal(len(select_page_element.SeleniumSelect.mock_calls), 1) - assert_equal(select_page_element.SeleniumSelect().mock_calls, - [mock.call.select_by_visible_text('new option value')]) + select_page_element.SeleniumSelect.assert_called() + select_page_element.SeleniumSelect().select_by_visible_text.assert_called_with('new option value') def test_click_button(self): - self.driver_wrapper.driver.find_element.return_value = mock_element + self.driver_wrapper.driver.find_element.return_value = self.mock_element LoginPageObject().login.click() - assert_equal(mock_element.click.mock_calls, [mock.call()]) + self.mock_element.click.assert_called() diff --git a/toolium/test/pageelements/test_page_element.py b/toolium/test/pageelements/test_page_element.py index a03172a2..29b1e9b2 100644 --- a/toolium/test/pageelements/test_page_element.py +++ b/toolium/test/pageelements/test_page_element.py @@ -19,9 +19,9 @@ import unittest import mock -import six from nose.tools import assert_equal, assert_is_not_none, assert_is_none from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webelement import WebElement from toolium.driver_wrapper import DriverWrapper from toolium.driver_wrappers_pool import DriverWrappersPool @@ -32,13 +32,6 @@ mock_element = None -@mock.patch('selenium.webdriver.remote.webelement.WebElement', spec=True) -def get_mock_element(WebElement): - web_element = WebElement.return_value - web_element.find_element.return_value = child_element - return web_element - - class RegisterPageObject(PageObject): username = PageElement(By.XPATH, '//input[0]') password = PageElement(By.ID, 'password', username) @@ -53,7 +46,8 @@ class TestPageElement(unittest.TestCase): def setUp(self): """Create a new mock element and a new driver before each test""" global mock_element - mock_element = get_mock_element() + mock_element = mock.MagicMock(spec=WebElement) + mock_element.find_element.return_value = child_element # Reset wrappers pool values DriverWrappersPool._empty_pool() @@ -72,40 +66,40 @@ def test_locator(self): def test_get_web_element(self): RegisterPageObject().username.web_element - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, [mock.call(By.XPATH, '//input[0]')]) + self.driver_wrapper.driver.find_element.assert_called_with(By.XPATH, '//input[0]') def test_get_web_element_init_page(self): RegisterPageObject().language.web_element - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, [mock.call(By.ID, 'language')]) + self.driver_wrapper.driver.find_element.assert_called_with(By.ID, 'language') def test_get_web_element_with_parent(self): self.driver_wrapper.driver.find_element.return_value = mock_element web_element = RegisterPageObject().password.web_element assert_equal(web_element, child_element) - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, [mock.call(By.XPATH, '//input[0]')]) - assert_equal(mock_element.find_element.mock_calls, [mock.call(By.ID, 'password')]) + self.driver_wrapper.driver.find_element.assert_called_with(By.XPATH, '//input[0]') + mock_element.find_element.assert_called_with(By.ID, 'password') def test_get_web_element_with_parent_locator(self): self.driver_wrapper.driver.find_element.return_value = mock_element web_element = RegisterPageObject().address.web_element assert_equal(web_element, child_element) - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, [mock.call(By.ID, 'parent')]) - assert_equal(mock_element.find_element.mock_calls, [mock.call(By.ID, 'address')]) + self.driver_wrapper.driver.find_element.assert_called_with(By.ID, 'parent') + mock_element.find_element.assert_called_with(By.ID, 'address') def test_get_web_element_with_parent_web_element(self): web_element = RegisterPageObject().email.web_element assert_equal(web_element, child_element) - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, []) - assert_equal(mock_element.find_element.mock_calls, [mock.call(By.ID, 'email')]) + self.driver_wrapper.driver.find_element.assert_not_called() + mock_element.find_element.assert_called_with(By.ID, 'email') def test_get_web_element_in_test(self): PageElement(By.XPATH, '//input[0]').web_element - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, [mock.call(By.XPATH, '//input[0]')]) + self.driver_wrapper.driver.find_element.assert_called_with(By.XPATH, '//input[0]') def test_get_web_element_two_times(self): login_page = RegisterPageObject() @@ -113,12 +107,7 @@ def test_get_web_element_two_times(self): login_page.username.web_element # Check that find_element is not called the second time - if six.PY2: - second_call = mock.call().__nonzero__() - else: - second_call = mock.call().__bool__() - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, - [mock.call(By.XPATH, '//input[0]'), second_call]) + self.driver_wrapper.driver.find_element.assert_called_with(By.XPATH, '//input[0]') def test_get_web_element_two_elements(self): login_page = RegisterPageObject() @@ -126,8 +115,8 @@ def test_get_web_element_two_elements(self): login_page.language.web_element # Check that find_element is called two times - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, - [mock.call(By.XPATH, '//input[0]'), mock.call(By.ID, 'language')]) + self.driver_wrapper.driver.find_element.assert_has_calls( + [mock.call(By.XPATH, '//input[0]'), mock.call(By.ID, 'language')]) def test_get_web_element_two_objects(self): login_page = RegisterPageObject() @@ -136,8 +125,8 @@ def test_get_web_element_two_objects(self): second_login_page.language.web_element # Check that find_element is called two times - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, - [mock.call(By.ID, 'language'), mock.call(By.ID, 'language')]) + self.driver_wrapper.driver.find_element.assert_has_calls( + [mock.call(By.ID, 'language'), mock.call(By.ID, 'language')]) def test_reset_object(self): login_page = RegisterPageObject() diff --git a/toolium/test/pageelements/test_page_elements.py b/toolium/test/pageelements/test_page_elements.py index 58b5ad1f..f35d647a 100644 --- a/toolium/test/pageelements/test_page_elements.py +++ b/toolium/test/pageelements/test_page_elements.py @@ -21,6 +21,7 @@ import mock from nose.tools import assert_equal, assert_is_instance, assert_is from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webelement import WebElement from toolium.driver_wrapper import DriverWrapper from toolium.driver_wrappers_pool import DriverWrappersPool @@ -29,14 +30,6 @@ child_elements = ['child_element_1', 'child_element_2'] other_child_elements = ['child_element_3', 'child_element_4'] -mock_element = None - - -@mock.patch('selenium.webdriver.remote.webelement.WebElement', spec=True) -def get_mock_element(WebElement): - web_element = WebElement.return_value - web_element.find_elements.return_value = child_elements - return web_element class LoginPageObject(PageObject): @@ -48,8 +41,9 @@ class LoginPageObject(PageObject): class TestPageElements(unittest.TestCase): def setUp(self): """Create a new mock element and a new driver before each test""" - global mock_element - mock_element = get_mock_element() + # Create a mock element + self.mock_element = mock.MagicMock(spec=WebElement) + self.mock_element.find_elements.return_value = child_elements # Reset wrappers pool values DriverWrappersPool._empty_pool() @@ -62,23 +56,23 @@ def setUp(self): def test_get_web_elements(self): LoginPageObject().inputs.web_elements - assert_equal(self.driver_wrapper.driver.find_elements.mock_calls, [mock.call(By.XPATH, '//input')]) + self.driver_wrapper.driver.find_elements.assert_called_with(By.XPATH, '//input') def test_get_web_elements_with_parent_locator(self): - self.driver_wrapper.driver.find_element.return_value = mock_element + self.driver_wrapper.driver.find_element.return_value = self.mock_element web_elements = LoginPageObject().inputs_parent.web_elements assert_equal(web_elements, child_elements) - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, [mock.call(By.ID, 'parent')]) - assert_equal(mock_element.find_elements.mock_calls, [mock.call(By.XPATH, '//input')]) + self.driver_wrapper.driver.find_element.assert_called_with(By.ID, 'parent') + self.mock_element.find_elements.assert_called_with(By.XPATH, '//input') def test_get_page_elements(self): self.driver_wrapper.driver.find_elements.return_value = child_elements page_elements = LoginPageObject().inputs.page_elements # Check that find_elements has been called just one time - assert_equal(self.driver_wrapper.driver.find_elements.mock_calls, [mock.call(By.XPATH, '//input')]) - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, []) + self.driver_wrapper.driver.find_elements.assert_called_with(By.XPATH, '//input') + self.driver_wrapper.driver.find_element.assert_not_called() # Check that the response is a list of 2 PageElement with the expected web element assert_equal(len(page_elements), 2) @@ -94,8 +88,8 @@ def test_get_page_elements_and_web_elements(self): web_elements = inputs.web_elements # Check that find_elements has been called just one time - assert_equal(self.driver_wrapper.driver.find_elements.mock_calls, [mock.call(By.XPATH, '//input')]) - assert_equal(self.driver_wrapper.driver.find_element.mock_calls, []) + self.driver_wrapper.driver.find_elements.assert_called_with(By.XPATH, '//input') + self.driver_wrapper.driver.find_element.assert_not_called() # Check that the response is a list of 2 PageElement with the expected web element assert_equal(len(page_elements), 2) diff --git a/toolium/test/pageobjects/test_page_object.py b/toolium/test/pageobjects/test_page_object.py index b4e8bb45..872d0857 100644 --- a/toolium/test/pageobjects/test_page_object.py +++ b/toolium/test/pageobjects/test_page_object.py @@ -21,6 +21,7 @@ import mock from nose.tools import assert_equal, assert_is_not_none, assert_is_none from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webelement import WebElement from toolium.driver_wrapper import DriverWrapper from toolium.driver_wrappers_pool import DriverWrappersPool @@ -31,13 +32,6 @@ mock_element = None -@mock.patch('selenium.webdriver.remote.webelement.WebElement', spec=True) -def get_mock_element(WebElement): - web_element = WebElement.return_value - web_element.find_element.return_value = child_element - return web_element - - class MenuPageObject(PageObject): register = PageElement(By.ID, 'register') @@ -66,7 +60,8 @@ class TestPageObject(unittest.TestCase): def setUp(self): """Create a new mock element and a new driver before each test""" global mock_element - mock_element = get_mock_element() + mock_element = mock.MagicMock(spec=WebElement) + mock_element.find_element.return_value = child_element # Reset wrappers pool values DriverWrappersPool._empty_pool() diff --git a/toolium/test/test_config_driver.py b/toolium/test/test_config_driver.py index da3b42cd..79ec0d51 100644 --- a/toolium/test/test_config_driver.py +++ b/toolium/test/test_config_driver.py @@ -189,9 +189,9 @@ def test_create_remote_driver_firefox(self, webdriver_mock): config_driver = ConfigDriver(self.config) # Firefox profile mock - profile_mock = lambda: None # Create an empty object - setattr(profile_mock, 'encoded', 'encoded profile') - config_driver._create_firefox_profile = mock.MagicMock(return_value=profile_mock) + class ProfileMock(object): + encoded = 'encoded profile' + config_driver._create_firefox_profile = mock.MagicMock(return_value=ProfileMock()) config_driver._create_remote_driver() capabilities = DesiredCapabilities.FIREFOX diff --git a/toolium/test/test_driver_wrapper.py b/toolium/test/test_driver_wrapper.py index 75ce942d..51f4d1ca 100644 --- a/toolium/test/test_driver_wrapper.py +++ b/toolium/test/test_driver_wrapper.py @@ -364,12 +364,11 @@ def test_configure_change_configuration_file(self): # Check that configuration has been initialized assert_equal('android', self.driver_wrapper.config.get('Driver', 'type')) - @mock.patch('toolium.driver_wrapper.ConfigDriver') - def test_connect(self, ConfigDriver): + @mock.patch('toolium.driver_wrapper.ConfigDriver.create_driver') + def test_connect(self, create_driver): # Mock data expected_driver = mock.MagicMock() - instance = ConfigDriver.return_value - instance.create_driver.return_value = expected_driver + create_driver.return_value = expected_driver self.driver_wrapper.utils = mock.MagicMock() # Connect and check the returned driver diff --git a/toolium/test/test_utils.py b/toolium/test/test_utils.py index 52eeaa54..2087db59 100644 --- a/toolium/test/test_utils.py +++ b/toolium/test/test_utils.py @@ -42,6 +42,21 @@ ) +def get_mock_element(x, y, height, width): + """Create a mock element with custom location and size + + :param x: x location + :param y: y location + :param height: element height + :param width: element width + :returns: mock element + """ + mock_element = mock.MagicMock(spec=WebElement) + mock_element.location = {'x': x, 'y': y} + mock_element.size = {'height': height, 'width': width} + return mock_element + + @ddt class UtilsTests(unittest.TestCase): def setUp(self): @@ -328,11 +343,3 @@ def test_get_web_element_from_none(self): def test_get_web_element_from_unknown(self): web_element = self.utils.get_web_element(dict()) assert_is_none(web_element) - - -@mock.patch('selenium.webdriver.remote.webelement.WebElement', spec=True) -def get_mock_element(WebElement, x, y, height, width): - web_element = WebElement.return_value - web_element.location = {'x': x, 'y': y} - web_element.size = {'height': height, 'width': width} - return web_element diff --git a/toolium/test/test_visual_test.py b/toolium/test/test_visual_test.py index d230ff32..25f1555d 100644 --- a/toolium/test/test_visual_test.py +++ b/toolium/test/test_visual_test.py @@ -35,6 +35,7 @@ from toolium.config_files import ConfigFiles from toolium.driver_wrapper import DriverWrappersPool from toolium.driver_wrapper import DriverWrapper +from toolium.test.test_utils import get_mock_element class VisualTests(unittest.TestCase): @@ -150,7 +151,9 @@ def test_compare_files_size_fail(self): self.visual.compare_files(self._testMethodName, self.file_v1, self.file_small, 0) def test_get_html_row(self): - expected_row = 'test_get_html_row' + expected_row = 'test_get_html_row' row = self.visual._get_html_row('diff', self._testMethodName, self.file_v1, self.file_v2) assertRegex(self, row, expected_row) @@ -420,11 +423,3 @@ def test_assert_screenshot_str_threshold(self): def test_assert_screenshot_greater_threshold(self): with assert_raises(TypeError): self.visual.assert_screenshot(None, 'screenshot_full', threshold=2) - - -@mock.patch('selenium.webdriver.remote.webelement.WebElement', spec=True) -def get_mock_element(WebElement, x, y, height, width): - web_element = WebElement.return_value - web_element.location = {'x': x, 'y': y} - web_element.size = {'height': height, 'width': width} - return web_element diff --git a/toolium/utils.py b/toolium/utils.py index 8d68c950..3f3b31ea 100644 --- a/toolium/utils.py +++ b/toolium/utils.py @@ -29,7 +29,7 @@ import requests from selenium.webdriver.remote.webelement import WebElement -from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.ui import WebDriverWait from selenium.common.exceptions import NoSuchElementException, TimeoutException @@ -124,7 +124,8 @@ def wait_until_element_visible(self, locator, timeout=10): :returns: the element if it is visible :rtype: selenium.webdriver.remote.webelement.WebElement or appium.webdriver.webelement.WebElement """ - return WebDriverWait(self.driver_wrapper.driver, timeout).until(EC.visibility_of_element_located(locator)) + return WebDriverWait(self.driver_wrapper.driver, timeout).until( + expected_conditions.visibility_of_element_located(locator)) def wait_until_element_not_visible(self, locator, timeout=10): """Search element by locator and wait until it is not visible @@ -137,7 +138,8 @@ def wait_until_element_not_visible(self, locator, timeout=10): # Remove implicit wait self.driver_wrapper.driver.implicitly_wait(0) # Wait for invisibility - element = WebDriverWait(self.driver_wrapper.driver, timeout).until(EC.invisibility_of_element_located(locator)) + element = WebDriverWait(self.driver_wrapper.driver, timeout).until( + expected_conditions.invisibility_of_element_located(locator)) # Restore implicit wait from properties self.set_implicit_wait() return element diff --git a/toolium/visual_test.py b/toolium/visual_test.py index 4b8cba68..1db55d8a 100644 --- a/toolium/visual_test.py +++ b/toolium/visual_test.py @@ -127,8 +127,8 @@ def assert_screenshot(self, element, filename, file_suffix=None, threshold=0, ex report_name = '{}
({})'.format(file_suffix, filename) # Get screenshot and modify it - if self.driver_wrapper.is_ios_test() or self.driver_wrapper.is_android_web_test() or ( - exclude_web_elements and len(exclude_web_elements) > 0) or web_element: + if (web_element or (exclude_web_elements and len(exclude_web_elements) > 0) or + self.driver_wrapper.is_ios_test() or self.driver_wrapper.is_android_web_test()): img = Image.open(BytesIO(self.driver_wrapper.driver.get_screenshot_as_png())) img = self.mobile_resize(img) img = self.exclude_elements(img, exclude_web_elements)