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

Source Code for Module tlib.base.SeleniumTester

  1  import os 
  2  import base64 
  3  import uuid 
  4  # noinspection PyPackageRequirements 
  5  import pytest 
  6  # noinspection PyPackageRequirements 
  7  from selenium import webdriver 
  8  from _pytest.python import FixtureRequest 
  9  from _pytest.mark import MarkInfo 
 10  # noinspection PyPackageRequirements 
 11  import jinja2 
 12  from tlib.base import TestHelper 
 13  from tlib.base.PytestTester import PytestTester 
 14  from selenium.webdriver.support.ui import WebDriverWait 
 15  from selenium.webdriver.support import expected_conditions 
 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 htm_file = "%(id)s.htm" % { "id": uuid.uuid4() } 159 relative_filename = os.path.join(self.__class__._test_case_id, htm_file) 160 full_filename = os.path.join(self.screenshot_folder(), relative_filename) 161 162 f = open(full_filename, "w") 163 try: 164 f.write(html) 165 finally: 166 f.close() 167 168 #Append current screenshot file to list of screenshots 169 self.__class__._screenshot_report[self.__class__._test_case_id + " - " + request.keywords.node.name] = relative_filename
170 171 request.addfinalizer(generate_screenshots) 172 173
174 - def navigate(self, page, save_screenshot=True):
175 """ 176 Navigate to "page" 177 """ 178 self.test_logger.info("Navigating to %s" % page) 179 self.browser.get(page) 180 if save_screenshot: 181 self.save_screenshot("Navigate to %s" % page)
182 183
184 - def go_home(self):
185 """ 186 Navigate to home page 187 """ 188 self.navigate(self.homepage, save_screenshot=False) 189 self.save_screenshot("Homepage")
190 191
192 - def save_screenshot(self, description):
193 """ 194 Saves screen shot for the current page 195 """ 196 197 def get_params(): 198 if self.__class__._test_params is None: 199 return "" 200 else: 201 return self.__class__._test_params
202 203 #Waits until page is loaded 204 self._tlib_logger.debug("Saving screenshot") 205 self.wait_for_page_loaded() 206 207 #Folder containing images for test case 208 #It contains a random string in case there are multiple tests with the same TC Id (different parameters) 209 rndstr = base64.urlsafe_b64encode(".".join([self.__class__._test_case_id, get_params()])) 210 test_folder = os.path.join(self.screenshot_folder(), self.__class__._test_case_id, rndstr) 211 212 try: 213 os.makedirs(test_folder) 214 except WindowsError: 215 pass 216 217 #Get number of existing images 218 i = len(os.listdir(test_folder)) + 1 219 220 #Get filename 221 img_filename = "%02d.jpg" % i 222 full_path = os.path.join(test_folder, img_filename) 223 224 self.__class__._screenshots[i] = {"filename": "%s/%s" % (rndstr, img_filename), 225 "description": description} 226 227 self.browser.get_screenshot_as_file(full_path) 228 229
230 - def wait_for_page_loaded(self, timeout=10):
231 """ 232 Waist until document.readyState is equal to complete 233 @type timeout: Integer 234 @param timeout: Number of seconds before timing out 235 """ 236 if self.browser.execute_script("return document.readyState") == "complete": 237 self._tlib_logger.debug("Page '%s' already loaded" % self.browser.current_url) 238 return 239 else: 240 self._tlib_logger.debug("Waiting for '%s' to load" % self.browser.current_url) 241 242 condition = lambda *args: self.browser.execute_script("return document.readyState") == "complete" 243 try: 244 WebDriverWait(self.browser, timeout).until(condition) 245 except TimeoutException: 246 self.test_logger.error('Timeout while waiting for page to load') 247 pytest.fail('Timeout while waiting for page to load') 248 249 self._tlib_logger.debug("Page '%s' finished loading" % self.browser.current_url)
250 251 @pytest.fixture(scope='function', autouse=True)
252 - def setup_method(self, request):
253 """ 254 Goes to homepage before each test, unless marker skipsetup is given 255 """ 256 #Get all markers 257 marks = {} 258 for k,v in request.node.function.__dict__.iteritems(): 259 if isinstance(v, MarkInfo): 260 marks[k] = v 261 262 #Don't go to home is skipsetup marker was given 263 if not marks.has_key('skipsetup'): 264 self.browser.delete_all_cookies() 265 self.go_home() 266 else: 267 self.test_logger.info("Skipping setup")
268 269
270 - def wait_for_element_to_be_visible(self, locator_strategy, locator_string, error_msg=None, timeout=10):
271 try: 272 WebDriverWait(self.browser, timeout).until(expected_conditions.visibility_of_element_located((locator_strategy, locator_string))) 273 except TimeoutException: 274 if error_msg is None: 275 error_msg = "Timeout while waiting for element '%s' to be visible" % locator_string 276 self.save_screenshot("[ERROR] %s" % error_msg) 277 pytest.fail(error_msg)
278 279
280 - def wait_for_element_to_be_clickable(self, locator_strategy, locator_string, error_msg=None, timeout=10):
281 try: 282 WebDriverWait(self.browser, timeout).until(expected_conditions.element_to_be_clickable((locator_strategy, locator_string))) 283 except TimeoutException: 284 if error_msg is None: 285 error_msg = "Timeout while waiting for element '%s' to be clickable" % locator_string 286 self.save_screenshot("[ERROR] %s" % error_msg) 287 pytest.fail(error_msg)
288 289
290 - def wait_for_element_to_be_present(self, locator_strategy, locator_string, error_msg=None, timeout=10):
291 try: 292 WebDriverWait(self.browser, timeout).until(expected_conditions.alert_is_present((locator_strategy, locator_string))) 293 except TimeoutException: 294 if error_msg is None: 295 error_msg = "Timeout while waiting for element '%s' to be present" % locator_string 296 self.save_screenshot("[ERROR] %s" % error_msg) 297 pytest.fail(error_msg)
298 299
300 - def wait_for_element_to_be_selected(self, locator_strategy, locator_string, error_msg=None, timeout=10):
301 try: 302 WebDriverWait(self.browser, timeout).until(expected_conditions.element_located_to_be_selected((locator_strategy, locator_string))) 303 except TimeoutException: 304 if error_msg is None: 305 error_msg = "Timeout while waiting for element '%s' to be selected" % locator_string 306 self.save_screenshot("[ERROR] %s" % error_msg) 307 pytest.fail(error_msg)
308 309
310 - def wait_for_element_to_be_invisible(self, locator_strategy, locator_string, error_msg=None, timeout=10):
311 try: 312 WebDriverWait(self.browser, timeout).until(expected_conditions.invisibility_of_element_located((locator_strategy, locator_string))) 313 except TimeoutException: 314 if error_msg is None: 315 error_msg = "Timeout while waiting for element '%s' to be invisible" % locator_string 316 self.save_screenshot("[ERROR] %s" % error_msg) 317 pytest.fail(error_msg)
318 319
320 - def wait_for_test_to_be_present_in_element(self, locator_strategy, locator_string, text, error_msg=None, timeout=10):
321 try: 322 WebDriverWait(self.browser, timeout).until(expected_conditions.text_to_be_present_in_element((locator_strategy, locator_string), text)) 323 except TimeoutException: 324 if error_msg is None: 325 error_msg = "Timeout while waiting for text %(text)s to be present in element '%(element)s'" % {"text": text, "element":locator_string} 326 self.save_screenshot("[ERROR] %s" % error_msg) 327 pytest.fail(error_msg)
328 329
330 - def wait_for_test_to_be_present_in_element_value(self, locator_strategy, locator_string, text, error_msg=None, timeout=10):
331 try: 332 WebDriverWait(self.browser, timeout).until(expected_conditions.text_to_be_present_in_element_value((locator_strategy, locator_string), text)) 333 except TimeoutException: 334 if error_msg is None: 335 error_msg = "Timeout while waiting for text %(text)s to be present in the value of element '%(element)s'" % {"text": text, "element":locator_string} 336 self.save_screenshot("[ERROR] %s" % error_msg) 337 pytest.fail(error_msg)
338