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

Source Code for Module tlib.base.SeleniumTester

  1  import os 
  2   
  3  __author__ = 'AOsorio1' 
  4   
  5  # noinspection PyPackageRequirements 
  6  import pytest 
  7  # noinspection PyPackageRequirements 
  8  from selenium import webdriver 
  9  from _pytest.python import FixtureRequest 
 10  from _pytest.mark import MarkInfo 
 11  # noinspection PyPackageRequirements 
 12  import jinja2 
 13  from tlib.base import TestHelper 
 14  from tlib.base.PytestTester import PytestTester 
 15  from selenium.webdriver.support.ui import WebDriverWait 
 16  from selenium.common.exceptions import NoSuchElementException, ElementNotVisibleException, TimeoutException 
 17  import logging 
18 19 20 # noinspection PyMethodParameters 21 # noinspection PyUnresolvedReferences 22 -class SeleniumTester(PytestTester):
23 24 homepage = "" 25 26 _test_logger = None # Reference to test 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 @property
42 - def browser(self):
43 """ 44 Instance of the WebDriver browser 45 @type: webdriver.Remote 46 """ 47 return self.__class__._browser
48 49 50 @property
51 - def test_logger(self):
52 """ 53 Logger object to log test information 54 @type: logging 55 """ 56 return self.__class__._test_logger
57 58 59 @staticmethod
60 - def screenshot_folder():
61 """ 62 Returns project's screenshot folder 63 This method must be defined in subclasses 64 """ 65 raise NotImplementedError("Subclasses should implement this!")
66 67 68 @pytest.fixture(scope='class', autouse=True)
69 - def initialize_class(self, test_logger, browser):
70 """ 71 @type test_logger: logging 72 @type browser: webdriver.Remote 73 Stores an instance of browser and test_logger 74 """ 75 self.__class__._test_logger = test_logger 76 self.__class__._browser = browser
77 78 79 @pytest.fixture(scope='class', autouse=True)
80 - def generate_screenshot_report(self, request):
81 """ 82 Generates HTML page with all test case results for the class 83 @type request: FixtureRequest 84 """ 85 self.__class__._screenshot_report = {} 86 87 def generate_report(): 88 if len(self.__class__._screenshot_report) > 0: 89 #Generate HTML based on template 90 html = self.__class__._screenshot_report_template.render(test_class=self.__class__.__name__, 91 test_case_id=self.__class__._test_case_id, files=self.__class__._screenshot_report) 92 93 html_file = "%s.html" % self.__class__.__name__ 94 full_filename = os.path.join(self.screenshot_folder(), html_file) 95 96 f = open(full_filename, "w") 97 try: 98 f.write(html) 99 finally: 100 f.close()
101 102 request.addfinalizer(generate_report)
103 104 105 @pytest.fixture(scope='function', autouse=True)
106 - def generate_test_case_screenshot(self, request):
107 """ 108 Generates HTML page with screenshots for each test 109 @type request: FixtureRequest 110 """ 111 self.__class__._test_params = request.keywords.node._genid 112 self.__class__._screenshots = {} 113 114 #Get marker testcasename or use a default if there is none 115 marker = request.node.get_marker("testcasename") 116 if marker is None: 117 self.__class__._test_case_id = "UNKNOWN_TEST_CASE_ID" 118 else: 119 self.__class__._test_case_id = marker.args[0] 120 121 122 def generate_screenshots(): 123 if len(self.__class__._screenshots) > 0: 124 #Generate HTML based on template 125 html = self.__class__._tc_screenshot_template.render(test_case_id=self.__class__._test_case_id, 126 test_case_name=request.keywords.node.name, 127 screenshots=self.__class__._screenshots) 128 129 html_file = "%s.html" % self.__class__._test_params 130 relative_filename = os.path.join(self.__class__._test_case_id, html_file) 131 full_filename = os.path.join(self.screenshot_folder(), relative_filename) 132 133 f = open(full_filename, "w") 134 try: 135 f.write(html) 136 finally: 137 f.close() 138 139 #Append current screenshot file to list of screenshots 140 self.__class__._screenshot_report[request.keywords.node.name] = relative_filename
141 142 request.addfinalizer(generate_screenshots) 143 144
145 - def navigate(self, page, save_screenshot=True):
146 """ 147 Navigate to "page" 148 """ 149 self.test_logger.info("Navigating to %s" % page) 150 self.browser.get(page) 151 if save_screenshot: 152 self.save_screenshot("Navigate to %s" % page)
153 154
155 - def go_home(self):
156 """ 157 Navigate to home page 158 """ 159 self.navigate(self.homepage, save_screenshot=False) 160 self.save_screenshot("Homepage")
161 162
163 - def save_screenshot(self, description):
164 """ 165 Saves screen shot for the current page 166 """ 167 #Waits until page is loaded 168 self.wait_for_page_loaded() 169 170 #Folder containing images for test case 171 test_folder = os.path.join(self.screenshot_folder(), self.__class__._test_case_id, self.__class__._test_params) 172 173 try: 174 os.makedirs(test_folder) 175 except WindowsError: 176 pass 177 178 #Get number of existing images 179 i = len(os.listdir(test_folder)) + 1 180 181 #Get filename 182 img_filename = "%02d.jpg" % i 183 full_path = os.path.join(test_folder, img_filename) 184 185 self.__class__._screenshots[i] = {"filename": "%s/%s" % (self.__class__._test_params, img_filename), 186 "description": description} 187 188 self.browser.get_screenshot_as_file(full_path)
189 190
191 - def wait_for_page_loaded(self, timeout=10):
192 """ 193 Waist until document.readyState is equal to complete 194 """ 195 condition = lambda *args: self.browser.execute_script("return document.readyState") == "complete" 196 try: 197 WebDriverWait(self.browser, timeout*1000).until(condition) 198 except TimeoutException: 199 self.test_logger.error('Timeout while waiting for page to load') 200 pytest.fail('Timeout while waiting for page to load')
201 202 203 @pytest.fixture(scope='function', autouse=True)
204 - def setup_go_home(self, request):
205 """ 206 Goes to homepage before each test, unless marker skipsetup is given 207 """ 208 #Get all markers 209 marks = {} 210 for k,v in request.node.function.__dict__.iteritems(): 211 if isinstance(v, MarkInfo): 212 marks[k] = v 213 214 #Don't go to home is skipsetup marker was given 215 if not marks.has_key('skipsetup'): 216 self.go_home() 217 else: 218 self.test_logger.info("Skipping setup")
219