Package tlib :: Package base :: Module SeleniumTester
[hide private]
[frames] | no frames]

Source Code for Module tlib.base.SeleniumTester

  1  import os 
  2  import uuid 
  3  # noinspection PyPackageRequirements 
  4  import pytest 
  5  # noinspection PyPackageRequirements 
  6  from selenium import webdriver 
  7  from _pytest.python import FixtureRequest 
  8  from _pytest.mark import MarkInfo 
  9  # noinspection PyPackageRequirements 
 10  import jinja2 
 11  from tlib.base import TestHelper 
 12  from tlib.base.PytestTester import PytestTester 
 13  from selenium.webdriver.support.ui import WebDriverWait 
 14  from selenium.webdriver.support import expected_conditions 
 15  from selenium.webdriver.common.by import By 
 16  from selenium.common.exceptions import TimeoutException 
 17  import logging 
18 19 20 # noinspection PyMethodParameters 21 # noinspection PyUnresolvedReferences 22 -class SeleniumTester(PytestTester):
23 24 _homepage = "" 25 _test_logger = None # Reference to test logger 26 _tlib_logger = None # Reference to tlib logger 27 _browser = None 28 29 _test_case_id = None 30 _test_params = None 31 32 _jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(TestHelper.tlib_template_folder()), trim_blocks = True) 33 34 _screenshot_report = {} # List of tests for which there are screenshots 35 _screenshot_report_template = _jinja_env.get_template("screenshot_report.html") # Template for generating screenshot report 36 37 _screenshots = {} # Screenshots generated during a test case 38 _tc_screenshot_template = _jinja_env.get_template("testcase_screenshots.html") # Template for generating screenshots for a test case 39 40
41 - def _get_browser(self):
42 """ 43 Returns Instance of the WebDriver browser 44 """ 45 return self.__class__._browser
46 47
48 - def _set_browser(self, browser):
49 """ 50 Instance of the WebDriver browser 51 @type: webdriver.Remote 52 """ 53 self.__class__._browser = browser
54 55 browser = property(_get_browser, _set_browser) 56
57 - def _get_homepage(self):
58 """ 59 Instance of the WebDriver homepage 60 @type: webdriver.Remote 61 """ 62 return self.__class__._homepage
63 64
65 - def _set_homepage(self, homepage):
66 """ 67 Instance of the WebDriver homepage 68 @type: webdriver.Remote 69 """ 70 self.__class__._homepage = homepage
71 72 homepage = property(_get_homepage, _set_homepage) 73 74 75 @property
76 - def test_logger(self):
77 """ 78 Logger object to log test information 79 @type: logging 80 """ 81 return self.__class__._test_logger
82 83 84 @staticmethod
85 - def screenshot_folder():
86 """ 87 Returns project's screenshot folder 88 This method must be defined in subclasses 89 """ 90 raise NotImplementedError("Subclasses should implement this!")
91 92 93 @pytest.fixture(scope='class', autouse=True)
94 - def initialize_class(self, test_logger, tlib_logger, browser, base_url):
95 """ 96 @type test_logger: logging 97 @type browser: webdriver.Remote 98 Stores an instance of browser and test_logger 99 """ 100 self.__class__._test_logger = test_logger 101 self.__class__._tlib_logger = tlib_logger 102 self.browser = browser 103 self.homepage = base_url
104 105 106 @pytest.fixture(scope='class', autouse=True)
107 - def generate_screenshot_report(self, request):
108 """ 109 Generates HTML page with all test case results for the class 110 @type request: FixtureRequest 111 """ 112 self.__class__._screenshot_report = {} 113 114 def generate_report(): 115 if len(self.__class__._screenshot_report) > 0: 116 #Generate HTML based on template 117 html = self.__class__._screenshot_report_template.render(test_class=self.__class__.__name__, 118 files=self.__class__._screenshot_report) 119 120 htm_file = "%s.htm" % self.__class__.__name__ 121 full_filename = os.path.join(self.screenshot_folder(), htm_file) 122 123 f = open(full_filename, "w") 124 try: 125 f.write(html) 126 finally: 127 f.close()
128 129 request.addfinalizer(generate_report)
130 131 132 @pytest.fixture(scope='function', autouse=True)
133 - def generate_test_case_screenshot(self, request):
134 """ 135 Generates HTML page with screenshots for each test 136 @type request: FixtureRequest 137 """ 138 # noinspection PyProtectedMember 139 self.__class__._test_params = request.keywords.node._genid 140 self.__class__._screenshots = {} 141 142 #Get marker testcasename or use a default if there is none 143 marker = request.node.get_marker("testcasename") 144 if marker is None: 145 self._test_logger.warn("Test case doesn't have marker testcasename") 146 self.__class__._test_case_id = "UNKNOWN_TEST_CASE_ID" 147 else: 148 self.__class__._test_case_id = marker.args[0] 149 150 151 def generate_screenshots(): 152 if len(self.__class__._screenshots) > 0: 153 #Generate HTML based on template 154 html = self.__class__._tc_screenshot_template.render(test_case_id=self.__class__._test_case_id, 155 test_case_name=request.keywords.node.name, 156 screenshots=self.__class__._screenshots) 157 158 #Generate random id 159 guid = uuid.uuid4() 160 161 htm_file = "%(tc_name)s_%(id)s.htm" % { "tc_name": self.__class__._test_params, "id": guid } 162 relative_filename = os.path.join(self.__class__._test_case_id, htm_file) 163 full_filename = os.path.join(self.screenshot_folder(), relative_filename) 164 165 f = open(full_filename, "w") 166 try: 167 f.write(html) 168 finally: 169 f.close() 170 171 #Append current screenshot file to list of screenshots 172 self.__class__._screenshot_report[self.__class__._test_case_id + " - " + request.keywords.node.name] = relative_filename
173 174 request.addfinalizer(generate_screenshots) 175 176
177 - def navigate(self, page, save_screenshot=True):
178 """ 179 Navigate to "page" 180 """ 181 self.test_logger.info("Navigating to %s" % page) 182 self.browser.get(page) 183 if save_screenshot: 184 self.save_screenshot("Navigate to %s" % page)
185 186
187 - def go_home(self):
188 """ 189 Navigate to home page 190 """ 191 self.navigate(self.homepage, save_screenshot=False) 192 self.save_screenshot("Homepage")
193 194
195 - def save_screenshot(self, description):
196 """ 197 Saves screen shot for the current page 198 """ 199 #Waits until page is loaded 200 self._tlib_logger.debug("Saving screenshot") 201 self.wait_for_page_loaded() 202 203 #Folder containing images for test case 204 if self.__class__._test_params is None: 205 #Test is not parameterized 206 test_folder = os.path.join(self.screenshot_folder(), self.__class__._test_case_id) 207 else: 208 #Test is parameterized 209 test_folder = os.path.join(self.screenshot_folder(), self.__class__._test_case_id, self.__class__._test_params) 210 211 try: 212 os.makedirs(test_folder) 213 except WindowsError: 214 pass 215 216 #Get number of existing images 217 i = len(os.listdir(test_folder)) + 1 218 219 #Get filename 220 img_filename = "%02d.jpg" % i 221 full_path = os.path.join(test_folder, img_filename) 222 223 self.__class__._screenshots[i] = {"filename": "%s/%s" % (self.__class__._test_params, img_filename), 224 "description": description} 225 226 self.browser.get_screenshot_as_file(full_path)
227 228
229 - def wait_for_page_loaded(self, timeout=10):
230 """ 231 Waist until document.readyState is equal to complete 232 @type timeout: Integer 233 @param timeout: Number of seconds before timing out 234 """ 235 if self.browser.execute_script("return document.readyState") == "complete": 236 self._tlib_logger.debug("Page '%s' already loaded" % self.browser.current_url) 237 return 238 else: 239 self._tlib_logger.debug("Waiting for '%s' to load" % self.browser.current_url) 240 241 condition = lambda *args: self.browser.execute_script("return document.readyState") == "complete" 242 try: 243 WebDriverWait(self.browser, timeout).until(condition) 244 except TimeoutException: 245 self.test_logger.error('Timeout while waiting for page to load') 246 pytest.fail('Timeout while waiting for page to load') 247 248 self._tlib_logger.debug("Page '%s' finished loading" % self.browser.current_url)
249 250 @pytest.fixture(scope='function', autouse=True)
251 - def setup_method(self, request):
252 """ 253 Goes to homepage before each test, unless marker skipsetup is given 254 """ 255 #Get all markers 256 marks = {} 257 for k,v in request.node.function.__dict__.iteritems(): 258 if isinstance(v, MarkInfo): 259 marks[k] = v 260 261 #Don't go to home is skipsetup marker was given 262 if not marks.has_key('skipsetup'): 263 self.browser.delete_all_cookies() 264 self.go_home() 265 else: 266 self.test_logger.info("Skipping setup")
267 268
269 - def wait_for_element_to_be_visible(self, locator_strategy, locator_string, error_msg=None, timeout=10):
270 try: 271 WebDriverWait(self.browser, timeout).until(expected_conditions.visibility_of_element_located((locator_strategy, locator_string))) 272 except TimeoutException: 273 if error_msg is None: 274 error_msg = "Timeout while waiting for element '%s' to be visible" % locator_string 275 self.save_screenshot("[ERROR] %s" % error_msg) 276 pytest.fail(error_msg)
277 278
279 - def wait_for_element_to_be_clickable(self, locator_strategy, locator_string, error_msg=None, timeout=10):
280 try: 281 WebDriverWait(self.browser, timeout).until(expected_conditions.element_to_be_clickable((locator_strategy, locator_string))) 282 except TimeoutException: 283 if error_msg is None: 284 error_msg = "Timeout while waiting for element '%s' to be clickable" % locator_string 285 self.save_screenshot("[ERROR] %s" % error_msg) 286 pytest.fail(error_msg)
287 288
289 - def wait_for_element_to_be_present(self, locator_strategy, locator_string, error_msg=None, timeout=10):
290 try: 291 WebDriverWait(self.browser, timeout).until(expected_conditions.alert_is_present((locator_strategy, locator_string))) 292 except TimeoutException: 293 if error_msg is None: 294 error_msg = "Timeout while waiting for element '%s' to be present" % locator_string 295 self.save_screenshot("[ERROR] %s" % error_msg) 296 pytest.fail(error_msg)
297 298
299 - def wait_for_element_to_be_selected(self, locator_strategy, locator_string, error_msg=None, timeout=10):
300 try: 301 WebDriverWait(self.browser, timeout).until(expected_conditions.element_located_to_be_selected((locator_strategy, locator_string))) 302 except TimeoutException: 303 if error_msg is None: 304 error_msg = "Timeout while waiting for element '%s' to be selected" % locator_string 305 self.save_screenshot("[ERROR] %s" % error_msg) 306 pytest.fail(error_msg)
307 308
309 - def wait_for_element_to_be_invisible(self, locator_strategy, locator_string, error_msg=None, timeout=10):
310 try: 311 WebDriverWait(self.browser, timeout).until(expected_conditions.invisibility_of_element_located((locator_strategy, locator_string))) 312 except TimeoutException: 313 if error_msg is None: 314 error_msg = "Timeout while waiting for element '%s' to be invisible" % locator_string 315 self.save_screenshot("[ERROR] %s" % error_msg) 316 pytest.fail(error_msg)
317 318
319 - def wait_for_test_to_be_present_in_element(self, locator_strategy, locator_string, text, error_msg=None, timeout=10):
320 try: 321 WebDriverWait(self.browser, timeout).until(expected_conditions.text_to_be_present_in_element((locator_strategy, locator_string), text)) 322 except TimeoutException: 323 if error_msg is None: 324 error_msg = "Timeout while waiting for text %(text)s to be present in element '%(element)s'" % {"text": text, "element":locator_string} 325 self.save_screenshot("[ERROR] %s" % error_msg) 326 pytest.fail(error_msg)
327 328
329 - def wait_for_test_to_be_present_in_element_value(self, locator_strategy, locator_string, text, error_msg=None, timeout=10):
330 try: 331 WebDriverWait(self.browser, timeout).until(expected_conditions.text_to_be_present_in_element_value((locator_strategy, locator_string), text)) 332 except TimeoutException: 333 if error_msg is None: 334 error_msg = "Timeout while waiting for text %(text)s to be present in the value of element '%(element)s'" % {"text": text, "element":locator_string} 335 self.save_screenshot("[ERROR] %s" % error_msg) 336 pytest.fail(error_msg)
337