1 import os
2 import inspect
3
4 import pytest
5 import collections
6 from time import sleep
7
8 from _pytest.python import FixtureRequest
9
10 import jinja2
11 from tlib.base import TestHelper
12 from tlib.base import FileHelper
13 from tlib.base.PytestTester import PytestTester
14 from selenium.webdriver.common.by import By
15 from selenium.webdriver.support.ui import WebDriverWait
16 from selenium.webdriver.support import expected_conditions
17 from selenium.common.exceptions import TimeoutException, NoAlertPresentException, NoSuchElementException
18 from selenium.webdriver.remote.webelement import WebElement
19 from TestHelper import Singleton
25
26 __metaclass__ = Singleton
27
28 _driver = None
29
30 _folder_dest = None
31 _test_case_id = None
32 _test_case_name = None
33 _test_params = None
34
35 _jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(TestHelper.tlib_template_folder()),
36 trim_blocks=True)
37
38 _screenshot_report = None
39
40
41 _screenshot_report_template = _jinja_env.get_template("screenshot_report.html")
42
43 _screenshots = {}
44
45
46 _tc_screenshot_template = _jinja_env.get_template("testcase_screenshots.html")
47
48 _request = None
49
63
65 """
66 Will try to find a folder named "screenshot" starting from the file being executed and up to
67 three levels up
68
69 @return: str
70 """
71
72 curr_folder = os.path.dirname(self._request.fspath.strpath)
73
74
75 for i in range(1, 4):
76 curr_folder = os.path.abspath(os.path.join(curr_folder, os.pardir))
77
78
79 screenshot_folder = os.path.join(curr_folder, 'screenshots')
80 if os.path.exists(screenshot_folder):
81 return screenshot_folder
82
84 """
85 Gets a string based on test case id and name, taking into account if test case has already been run or not
86 @param tc_id: Test case id
87 @type tc_id: str
88 @type tc_name: str
89 """
90 i = 0
91 while True:
92 if i == 0:
93 filename = "%(tc_id)s_%(tc_params)s" % {"tc_id": tc_id, "tc_params": tc_params}
94 else:
95 filename = "%(tc_id)s_%(tc_params)s [retry %(cnt)d]" % \
96 {"tc_id": tc_id, "tc_params": tc_params, "cnt": i}
97
98 if not filename in self._screenshot_report:
99 return filename
100
101 i += 1
102
103 @pytest.fixture(scope='class', autouse=True)
105 """
106 @type request: FixtureRequest
107 """
108
109
110 self._screenshot_report = collections.OrderedDict()
111 self._folder_dest = os.path.basename(os.path.dirname(os.path.abspath(inspect.getfile(request.cls))))
112
113 def generate_report():
114 if len(self._screenshot_report) > 0:
115
116 html = self._screenshot_report_template.render(test_class=request.cls.__name__,
117 files=self._screenshot_report)
118
119 htm_file = "%s.htm" % self._folder_dest
120 full_filename = os.path.join(self.screenshot_folder(), htm_file)
121
122 f = open(full_filename, "w")
123 try:
124 f.write(html)
125 finally:
126 f.close()
127
128 request.addfinalizer(generate_report)
129
130 @pytest.fixture(scope='function', autouse=True)
182
183 request.addfinalizer(generate_report)
184
215
216 - def wait_for_page_loaded(self, timeout=10):
217 raise NotImplementedError("This method should be implemented by derived classes")
218
220 """
221 Waist until an alert is visible
222 @type timeout: Integer
223 @param timeout: Number of seconds before timing out
224 @rtype: bool
225 """
226 def is_alert_visible():
227 try:
228
229 alert = self._driver.switch_to_alert().text
230 return True
231 except NoAlertPresentException as e:
232 return False
233
234 condition = lambda *args: is_alert_visible()
235 try:
236 WebDriverWait(self._driver, timeout).until(condition)
237 return self._driver.switch_to_alert()
238 except TimeoutException:
239 self.test_logger.error('Timeout while waiting for alert to appear')
240 pytest.fail('Timeout while waiting for alert to appear')
241
243 """
244 Wait until an element becomes visible
245 @param locator_strategy: Location strategy to use
246 @type locator_strategy: By
247 @param locator_string: String used to locate element
248 @type locator_string: str
249 @param error_msg: Error string to show if element is not found
250 @type error_msg: str
251 @param timeout: Maximum time in seconds to wait for the element to be visible
252 @type timeout: int
253 @rtype: WebElement
254 """
255 try:
256 element = WebDriverWait(self._driver, timeout).\
257 until(expected_conditions.visibility_of_element_located((locator_strategy, locator_string)))
258 return element
259 except TimeoutException:
260 if error_msg is None:
261 error_msg = "Timeout while waiting for element '%s' to be visible" % locator_string
262 self.save_screenshot("[ERROR] %s" % error_msg)
263 pytest.fail(error_msg)
264
266 """
267 Wait until an element cna be clicked
268 @param locator_strategy: Location strategy to use
269 @type locator_strategy: By
270 @param locator_string: String used to locate element
271 @type locator_string: str
272 @param error_msg: Error string to show if element is not found
273 @type error_msg: str
274 @param timeout: Maximum time in seconds to wait for the element to be clickable
275 @type timeout: int
276 @rtype: WebElement
277 """
278 try:
279 element = WebDriverWait(self._driver, timeout).\
280 until(expected_conditions.element_to_be_clickable((locator_strategy, locator_string)))
281 return element
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
289 """
290 Wait until an element is present
291 @param locator_strategy: Location strategy to use
292 @type locator_strategy: By
293 @param locator_string: String used to locate element
294 @type locator_string: str
295 @param error_msg: Error string to show if element is not found
296 @type error_msg: str
297 @param timeout: Maximum time in seconds to wait for the element to be present
298 @type timeout: int
299 @rtype: WebElement
300 """
301 try:
302 element = WebDriverWait(self._driver, timeout).\
303 until(expected_conditions.presence_of_element_located((locator_strategy, locator_string)))
304 return element
305 except TimeoutException:
306 if error_msg is None:
307 error_msg = "Timeout while waiting for element '%s' to be present" % locator_string
308 self.save_screenshot("[ERROR] %s" % error_msg)
309 pytest.fail(error_msg)
310
312 """
313 Wait until an element is selected
314 @param locator_strategy: Location strategy to use
315 @type locator_strategy: By
316 @param locator_string: String used to locate element
317 @type locator_string: str
318 @param error_msg: Error string to show if element is not found
319 @type error_msg: str
320 @param timeout: Maximum time in seconds to wait for the element to be selected
321 @type timeout: int
322 @rtype: WebElement
323 """
324 try:
325 element = WebDriverWait(self._driver, timeout).\
326 until(expected_conditions.element_located_to_be_selected((locator_strategy, locator_string)))
327 return element
328 except TimeoutException:
329 if error_msg is None:
330 error_msg = "Timeout while waiting for element '%s' to be selected" % locator_string
331 self.save_screenshot("[ERROR] %s" % error_msg)
332 pytest.fail(error_msg)
333
335 """
336 Wait until an element becomes invisible
337 @param locator_strategy: Location strategy to use
338 @type locator_strategy: By
339 @param locator_string: String used to locate element
340 @type locator_string: str
341 @param error_msg: Error string to show if element is not found
342 @type error_msg: str
343 @param timeout: Maximum time in seconds to wait for the element to be hidden
344 @type timeout: int
345 @rtype: WebElement
346 """
347 try:
348 element = WebDriverWait(self._driver, timeout).\
349 until(expected_conditions.invisibility_of_element_located((locator_strategy, locator_string)))
350 return element
351 except TimeoutException:
352 if error_msg is None:
353 error_msg = "Timeout while waiting for element '%s' to be invisible" % locator_string
354 self.save_screenshot("[ERROR] %s" % error_msg)
355 pytest.fail(error_msg)
356
358 """
359 Wait until an element that moves on the screen stops moving
360 @param locator_strategy: Location strategy to use
361 @type locator_strategy: By
362 @param locator_string: String used to locate element
363 @type locator_string: str
364 @param error_msg: Error string to show if element is not found
365 @type error_msg: str
366 @param timeout: Maximum time in seconds to wait for the element to be visible
367 @type timeout: int
368 @rtype: WebElement
369 """
370 try:
371 element = WebDriverWait(self._driver, timeout).\
372 until(expected_conditions.visibility_of_element_located((locator_strategy, locator_string)))
373
374
375 old_location = {'x': 0, 'y': 0}
376 while old_location != element.location:
377 self.tlib_logger.debug("Pop-up is still moving. Previous position: %s, current position: %s" %
378 (old_location, element.location))
379 old_location = element.location
380 sleep(0.1)
381 element = self._driver.find_element(locator_strategy, locator_string)
382
383 return element
384 except TimeoutException:
385 if error_msg is None:
386 error_msg = "Timeout while waiting for element '%s' to be visible" % locator_string
387 self.save_screenshot("[ERROR] %s" % error_msg)
388 pytest.fail(error_msg)
389
390 - def wait_for_text_to_be_present_in_element(self, locator_strategy, locator_string, text,
391 error_msg=None, timeout=10):
392 """
393 Wait for an element that contains specified text
394 @param locator_strategy: Location strategy to use
395 @type locator_strategy: By
396 @param locator_string: String used to locate element
397 @type locator_string: str
398 @param error_msg: Error string to show if element is not found
399 @type error_msg: str
400 @param timeout: Maximum time in seconds to wait
401 @type timeout: int
402 """
403 try:
404 WebDriverWait(self._driver, timeout).\
405 until(expected_conditions.text_to_be_present_in_element((locator_strategy, locator_string), text))
406 except TimeoutException:
407 if error_msg is None:
408 error_msg = "Timeout while waiting for text %(text)s to be present in element '%(element)s'" % \
409 {"text": text, "element": locator_string}
410 self.save_screenshot("[ERROR] %s" % error_msg)
411 pytest.fail(error_msg)
412
413 - def wait_for_text_to_be_present_in_element_value(self, locator_strategy, locator_string, text,
414 error_msg=None, timeout=10):
415 """
416 Wait for an element's value to contain some test
417 @param locator_strategy: Location strategy to use
418 @type locator_strategy: By
419 @param locator_string: String used to locate element
420 @type locator_string: str
421 @param error_msg: Error string to show if element is not found
422 @type error_msg: str
423 @param timeout: Maximum time in seconds to wait
424 @type timeout: int
425 """
426 try:
427 WebDriverWait(self._driver, timeout).\
428 until(expected_conditions.text_to_be_present_in_element_value((locator_strategy, locator_string), text))
429 except TimeoutException:
430 if error_msg is None:
431 error_msg = "Timeout while waiting for text %(text)s to be present " \
432 "in the value of element '%(element)s'" % {"text": text, "element": locator_string}
433 self.save_screenshot("[ERROR] %s" % error_msg)
434 pytest.fail(error_msg)
435
436
437 - def get_webelement_by_link_text(self, locator_string):
438 """
439 Get the webelement by link text
440 @param locator_string: String used to locate element
441 @type locator_string: str
442 @param error_msg: Error string to show if element is not found
443 @type error_msg: str
444 """
445 try:
446 return self.browser.find_element_by_link_text(locator_string)
447 except NoSuchElementException:
448 error_msg="Could not find the link: '%s'"
449 self.save_screenshot(error_msg % locator_string)
450 pytest.fail(error_msg % locator_string)
451
453 """
454 Get the webelement by xpath
455 @param locator_string: String used to locate element
456 @type locator_string: str
457 @param error_msg: Error string to show if element is not found
458 @type error_msg: str
459 """
460 try:
461 self.wait_for_element_to_be_visible(By.XPATH, locator_string)
462 return self.browser.find_element_by_xpath(locator_string)
463 except NoSuchElementException:
464 error_msg="Could not find the xpath: '%s'"
465 self.save_screenshot(error_msg % locator_string)
466 pytest.fail(error_msg % locator_string)
467
469 """
470 Get the webelement by CSS
471 @param locator_string: String used to locate element
472 @type locator_string: str
473 @param error_msg: Error string to show if element is not found
474 @type error_msg: str
475 """
476 try:
477 self.wait_for_element_to_be_visible(By.CSS_SELECTOR, locator_string)
478 return self.browser.find_element_by_css_selector(locator_string)
479 except NoSuchElementException:
480 error_msg="Could not find css: '%s'"
481 self.save_screenshot(error_msg % locator_string)
482 pytest.fail(error_msg %locator_string)
483
485 """
486 Get the webelement list by xpath
487 @param locator_string: String used to locate element
488 @type locator_string: str
489 @param error_msg: Error string to show if element is not found
490 @type error_msg: str
491 """
492 try:
493 return self.browser.find_elements_by_xpath(locator_string)
494 except NoSuchElementException:
495 error_msg="Could not find the link: '%s'"
496 self.save_screenshot(error_msg % locator_string)
497 pytest.fail(error_msg+ " '%s'" % locator_string)
498
500 """
501 Get the webelement list by CSS
502 @param locator_string: String used to locate element
503 @type locator_string: str
504 @param error_msg: Error string to show if element is not found
505 @type error_msg: str
506 """
507 try:
508 return self.browser.find_elements_by_css_selector(locator_string)
509 except NoSuchElementException:
510 error_msg="Could not find css: '%s'"
511 self.save_screenshot(error_msg % locator_string)
512 pytest.fail(error_msg % locator_string)
513