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
91 i = 0
92 while True:
93 if i == 0:
94 filename = "%(tc_id)s_%(tc_params)s" % {"tc_id": tc_id, "tc_params": tc_params}
95 else:
96 filename = "%(tc_id)s_%(tc_params)s [retry %(cnt)d]" % \
97 {"tc_id": tc_id, "tc_params": tc_params, "cnt": i}
98
99 if not filename in self._screenshot_report:
100 return filename
101
102 i += 1
103
104 @pytest.fixture(scope='class', autouse=True)
106 """
107 @type request: FixtureRequest
108 """
109
110
111 self._screenshot_report = collections.OrderedDict()
112
113 self._folder_dest = os.path.basename(os.path.dirname(os.path.abspath(inspect.getfile(request.cls))))
114
115 def generate_report():
116
117 if len(self._screenshot_report) > 0:
118
119 html = self._screenshot_report_template.render(test_class=request.cls.__name__,
120 files=self._screenshot_report)
121
122 htm_file = "%s.htm" % self._folder_dest
123 full_filename = os.path.join(self.screenshot_folder(), htm_file)
124
125 f = open(full_filename, "w")
126 try:
127 f.write(html)
128 finally:
129 f.close()
130
131 request.addfinalizer(generate_report)
132
133 @pytest.fixture(scope='function', autouse=True)
185
186 request.addfinalizer(generate_report)
187
216
217 - def wait_for_page_loaded(self, timeout=10):
218 raise NotImplementedError("This method should be implemented by derived classes")
219
221 """
222 Waist until an alert is visible
223 @type timeout: Integer
224 @param timeout: Number of seconds before timing out
225 @rtype: bool
226 """
227 def is_alert_visible():
228 try:
229
230 alert = self._driver.switch_to_alert().text
231 return True
232 except NoAlertPresentException as e:
233 return False
234
235 condition = lambda *args: is_alert_visible()
236 try:
237 WebDriverWait(self._driver, timeout).until(condition)
238 return self._driver.switch_to_alert()
239 except TimeoutException:
240 self.test_logger.error('Timeout while waiting for alert to appear')
241 pytest.fail('Timeout while waiting for alert to appear')
242
244 """
245 Wait until an element becomes visible
246 @param locator_strategy: Location strategy to use
247 @type locator_strategy: By
248 @param locator_string: String used to locate element
249 @type locator_string: str
250 @param error_msg: Error string to show if element is not found
251 @type error_msg: str
252 @param timeout: Maximum time in seconds to wait for the element to be visible
253 @type timeout: int
254 @rtype: WebElement
255 """
256 try:
257 element = WebDriverWait(self._driver, timeout).\
258 until(expected_conditions.visibility_of_element_located((locator_strategy, locator_string)))
259 return element
260 except TimeoutException:
261 if error_msg is None:
262 error_msg = "Timeout while waiting for element '%s' to be visible" % locator_string
263 self.save_screenshot("[ERROR] %s" % error_msg)
264 pytest.fail(error_msg)
265
267 """
268 Wait until an element cna be clicked
269 @param locator_strategy: Location strategy to use
270 @type locator_strategy: By
271 @param locator_string: String used to locate element
272 @type locator_string: str
273 @param error_msg: Error string to show if element is not found
274 @type error_msg: str
275 @param timeout: Maximum time in seconds to wait for the element to be clickable
276 @type timeout: int
277 @rtype: WebElement
278 """
279 try:
280 element = WebDriverWait(self._driver, timeout).\
281 until(expected_conditions.element_to_be_clickable((locator_strategy, locator_string)))
282 return element
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
290 """
291 Wait until an element is present
292 @param locator_strategy: Location strategy to use
293 @type locator_strategy: By
294 @param locator_string: String used to locate element
295 @type locator_string: str
296 @param error_msg: Error string to show if element is not found
297 @type error_msg: str
298 @param timeout: Maximum time in seconds to wait for the element to be present
299 @type timeout: int
300 @rtype: WebElement
301 """
302 try:
303 element = WebDriverWait(self._driver, timeout).\
304 until(expected_conditions.presence_of_element_located((locator_strategy, locator_string)))
305 return element
306 except TimeoutException:
307 if error_msg is None:
308 error_msg = "Timeout while waiting for element '%s' to be present" % locator_string
309 self.save_screenshot("[ERROR] %s" % error_msg)
310 pytest.fail(error_msg)
311
313 """
314 Wait until an element is selected
315 @param locator_strategy: Location strategy to use
316 @type locator_strategy: By
317 @param locator_string: String used to locate element
318 @type locator_string: str
319 @param error_msg: Error string to show if element is not found
320 @type error_msg: str
321 @param timeout: Maximum time in seconds to wait for the element to be selected
322 @type timeout: int
323 @rtype: WebElement
324 """
325 try:
326 element = WebDriverWait(self._driver, timeout).\
327 until(expected_conditions.element_located_to_be_selected((locator_strategy, locator_string)))
328 return element
329 except TimeoutException:
330 if error_msg is None:
331 error_msg = "Timeout while waiting for element '%s' to be selected" % locator_string
332 self.save_screenshot("[ERROR] %s" % error_msg)
333 pytest.fail(error_msg)
334
336 """
337 Wait until an element becomes invisible
338 @param locator_strategy: Location strategy to use
339 @type locator_strategy: By
340 @param locator_string: String used to locate element
341 @type locator_string: str
342 @param error_msg: Error string to show if element is not found
343 @type error_msg: str
344 @param timeout: Maximum time in seconds to wait for the element to be hidden
345 @type timeout: int
346 @rtype: WebElement
347 """
348 try:
349 element = WebDriverWait(self._driver, timeout).\
350 until(expected_conditions.invisibility_of_element_located((locator_strategy, locator_string)))
351 return element
352 except TimeoutException:
353 if error_msg is None:
354 error_msg = "Timeout while waiting for element '%s' to be invisible" % locator_string
355 self.save_screenshot("[ERROR] %s" % error_msg)
356 pytest.fail(error_msg)
357
359 """
360 Wait until an element that moves on the screen stops moving
361 @param locator_strategy: Location strategy to use
362 @type locator_strategy: By
363 @param locator_string: String used to locate element
364 @type locator_string: str
365 @param error_msg: Error string to show if element is not found
366 @type error_msg: str
367 @param timeout: Maximum time in seconds to wait for the element to be visible
368 @type timeout: int
369 @rtype: WebElement
370 """
371 try:
372 self.tlib_logger.debug("Waiting for element '%s' to be visible with locator strategy: %s" %
373 (locator_string, locator_strategy))
374 element = WebDriverWait(self._driver, timeout).\
375 until(expected_conditions.visibility_of_element_located((locator_strategy, locator_string)))
376
377 self.tlib_logger.debug("Waiting until element stops moving")
378
379 old_location = {'x': 0, 'y': 0}
380 while old_location != element.location:
381 self.tlib_logger.debug("Pop-up is still moving. Previous position: %s, current position: %s" %
382 (old_location, element.location))
383 old_location = element.location
384 sleep(0.1)
385 element = self._driver.find_element(locator_strategy, locator_string)
386
387 return element
388 except TimeoutException:
389 if error_msg is None:
390 error_msg = "Timeout while waiting for element '%s' to be visible" % locator_string
391 self.save_screenshot("[ERROR] %s" % error_msg)
392 pytest.fail(error_msg)
393
394 - def wait_for_text_to_be_present_in_element(self, locator_strategy, locator_string, text,
395 error_msg=None, timeout=10):
396 """
397 Wait for an element that contains specified text
398 @param locator_strategy: Location strategy to use
399 @type locator_strategy: By
400 @param locator_string: String used to locate element
401 @type locator_string: str
402 @param error_msg: Error string to show if element is not found
403 @type error_msg: str
404 @param timeout: Maximum time in seconds to wait
405 @type timeout: int
406 """
407 try:
408 WebDriverWait(self._driver, timeout).\
409 until(expected_conditions.text_to_be_present_in_element((locator_strategy, locator_string), text))
410 except TimeoutException:
411 if error_msg is None:
412 error_msg = "Timeout while waiting for text %(text)s to be present in element '%(element)s'" % \
413 {"text": text, "element": locator_string}
414 self.save_screenshot("[ERROR] %s" % error_msg)
415 pytest.fail(error_msg)
416
417 - def wait_for_text_to_be_present_in_element_value(self, locator_strategy, locator_string, text,
418 error_msg=None, timeout=10):
419 """
420 Wait for an element's value to contain some test
421 @param locator_strategy: Location strategy to use
422 @type locator_strategy: By
423 @param locator_string: String used to locate element
424 @type locator_string: str
425 @param error_msg: Error string to show if element is not found
426 @type error_msg: str
427 @param timeout: Maximum time in seconds to wait
428 @type timeout: int
429 """
430 try:
431 WebDriverWait(self._driver, timeout).\
432 until(expected_conditions.text_to_be_present_in_element_value((locator_strategy, locator_string), text))
433 except TimeoutException:
434 if error_msg is None:
435 error_msg = "Timeout while waiting for text %(text)s to be present " \
436 "in the value of element '%(element)s'" % {"text": text, "element": locator_string}
437 self.save_screenshot("[ERROR] %s" % error_msg)
438 pytest.fail(error_msg)
439
440
441 - def get_webelement_by_link_text(self, locator_string):
442 """
443 Get the webelement by link text
444 @param locator_string: String used to locate element
445 @type locator_string: str
446 @param error_msg: Error string to show if element is not found
447 @type error_msg: str
448 """
449 try:
450 return self.browser.find_element_by_link_text(locator_string)
451 except NoSuchElementException:
452 error_msg="Could not find the link: '%s'"
453 self.save_screenshot(error_msg % locator_string)
454 pytest.fail(error_msg % locator_string)
455
457 """
458 Get the webelement by xpath
459 @param locator_string: String used to locate element
460 @type locator_string: str
461 @param error_msg: Error string to show if element is not found
462 @type error_msg: str
463 """
464 try:
465 self.wait_for_element_to_be_visible(By.XPATH, locator_string)
466 return self.browser.find_element_by_xpath(locator_string)
467 except NoSuchElementException:
468 error_msg="Could not find the xpath: '%s'"
469 self.save_screenshot(error_msg % locator_string)
470 pytest.fail(error_msg % locator_string)
471
473 """
474 Get the webelement by CSS
475 @param locator_string: String used to locate element
476 @type locator_string: str
477 @param error_msg: Error string to show if element is not found
478 @type error_msg: str
479 """
480 try:
481 self.wait_for_element_to_be_visible(By.CSS_SELECTOR, locator_string)
482 return self.browser.find_element_by_css_selector(locator_string)
483 except NoSuchElementException:
484 error_msg="Could not find css: '%s'"
485 self.save_screenshot(error_msg % locator_string)
486 pytest.fail(error_msg %locator_string)
487
489 """
490 Get the webelement list by xpath
491 @param locator_string: String used to locate element
492 @type locator_string: str
493 @param error_msg: Error string to show if element is not found
494 @type error_msg: str
495 """
496 try:
497 return self.browser.find_elements_by_xpath(locator_string)
498 except NoSuchElementException:
499 error_msg="Could not find the link: '%s'"
500 self.save_screenshot(error_msg % locator_string)
501 pytest.fail(error_msg+ " '%s'" % locator_string)
502
504 """
505 Get the webelement list by CSS
506 @param locator_string: String used to locate element
507 @type locator_string: str
508 @param error_msg: Error string to show if element is not found
509 @type error_msg: str
510 """
511 try:
512 return self.browser.find_elements_by_css_selector(locator_string)
513 except NoSuchElementException:
514 error_msg="Could not find css: '%s'"
515 self.save_screenshot(error_msg % locator_string)
516 pytest.fail(error_msg % locator_string)
517