1
1
"""
2
- BaseCase gathers SeleniumBase libraries into a single file for easy calling.
2
+ The BaseCase class is the main gateway for using The SeleniumBase Framework.
3
+ It inherits Python's unittest.TestCase class, and runs with Pytest or Nose.
4
+ All tests using BaseCase automatically launch WebDriver browsers for tests.
5
+
3
6
Usage:
4
7
5
8
from seleniumbase import BaseCase
6
9
class MyTestClass(BaseCase):
7
- test_anything(self):
10
+ def test_anything(self):
8
11
# Write your code here. Example:
9
12
self.open("https://github.com/")
10
13
self.update_text("input.header-search-input", "SeleniumBase\n ")
11
14
self.click('a[href="/seleniumbase/SeleniumBase"]')
12
15
self.assert_element("div.repository-content")
13
16
....
14
17
15
- The methods here expand and improve existing WebDriver commands.
16
- Improvements include making WebDriver more robust and more reliable .
17
- Page elements are given enough time to load before taking action on them.
18
+ SeleniumBase methods expand and improve on existing WebDriver commands.
19
+ Improvements include making WebDriver more robust, reliable, and flexible .
20
+ Page elements are given enough time to load before WebDriver acts on them.
18
21
Code becomes greatly simplified and easier to maintain.
19
22
"""
20
23
@@ -74,7 +77,8 @@ def __init__(self, *args, **kwargs):
74
77
self ._page_check_count = 0
75
78
self ._page_check_failures = []
76
79
self ._html_report_extra = []
77
- self ._extra_drivers = []
80
+ self ._default_driver = None
81
+ self ._drivers_list = []
78
82
79
83
def open (self , url ):
80
84
self .driver .get (url )
@@ -612,8 +616,8 @@ def find_visible_elements(self, selector, by=By.CSS_SELECTOR):
612
616
by = By .LINK_TEXT
613
617
return page_actions .find_visible_elements (self .driver , selector , by )
614
618
615
- def is_element_in_frame (self , selector , by = By .CSS_SELECTOR ):
616
- """ Returns True if the selector's element is located in an iFrame .
619
+ def is_element_in_an_iframe (self , selector , by = By .CSS_SELECTOR ):
620
+ """ Returns True if the selector's element is located in an iframe .
617
621
Otherwise returns False. """
618
622
selector , by = self ._recalculate_selector (selector , by )
619
623
if self .is_element_present (selector , by = by ):
@@ -636,10 +640,11 @@ def is_element_in_frame(self, selector, by=By.CSS_SELECTOR):
636
640
self .switch_to_default_content ()
637
641
return False
638
642
639
- def enter_frame_of_element (self , selector , by = By .CSS_SELECTOR ):
640
- """ Returns the frame name of the selector's element if in an iFrame.
641
- Also enters the iFrame if the element was inside an iFrame.
642
- If the element is not in an iFrame, returns None. """
643
+ def switch_to_frame_of_element (self , selector , by = By .CSS_SELECTOR ):
644
+ """ Set driver control to the iframe of the element (assuming the
645
+ element is in a single-nested iframe) and returns the iframe name.
646
+ If element is not in an iframe, returns None, and nothing happens.
647
+ May not work if multiple iframes are nested within each other. """
643
648
selector , by = self ._recalculate_selector (selector , by )
644
649
if self .is_element_present (selector , by = by ):
645
650
return None
@@ -1420,54 +1425,90 @@ def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT):
1420
1425
return page_actions .wait_for_and_switch_to_alert (self .driver , timeout )
1421
1426
1422
1427
def switch_to_frame (self , frame , timeout = settings .SMALL_TIMEOUT ):
1428
+ """ Sets driver control to the specified browser frame. """
1423
1429
if self .timeout_multiplier and timeout == settings .SMALL_TIMEOUT :
1424
1430
timeout = self ._get_new_timeout (timeout )
1425
1431
page_actions .switch_to_frame (self .driver , frame , timeout )
1426
1432
1433
+ def switch_to_default_content (self ):
1434
+ """ Brings driver control outside the current iframe.
1435
+ (If driver control is inside an iframe, the driver control
1436
+ will be set to one level above the current frame. If the driver
1437
+ control is not currenly in an iframe, nothing will happen.) """
1438
+ self .driver .switch_to .default_content ()
1439
+
1440
+ def open_new_window (self , switch_to = True ):
1441
+ """ Opens a new browser tab/window and switches to it by default. """
1442
+ self .driver .execute_script ("window.open('');" )
1443
+ time .sleep (0.01 )
1444
+ if switch_to :
1445
+ self .switch_to_window (len (self .driver .window_handles ) - 1 )
1446
+
1427
1447
def switch_to_window (self , window , timeout = settings .SMALL_TIMEOUT ):
1428
1448
if self .timeout_multiplier and timeout == settings .SMALL_TIMEOUT :
1429
1449
timeout = self ._get_new_timeout (timeout )
1430
1450
page_actions .switch_to_window (self .driver , window , timeout )
1431
1451
1432
- def switch_to_default_content (self ):
1433
- self .driver . switch_to . default_content ( )
1452
+ def switch_to_default_window (self ):
1453
+ self .switch_to_window ( 0 )
1434
1454
1435
1455
def save_screenshot (self , name , folder = None ):
1436
1456
return page_actions .save_screenshot (self .driver , name , folder )
1437
1457
1438
1458
def get_new_driver (self , browser = None , headless = None ,
1439
- servername = None , port = None ,
1440
- proxy_string = None ):
1459
+ servername = None , port = None , proxy = None , switch_to = True ):
1441
1460
""" This method spins up an extra browser for tests that require
1442
1461
more than one. The first browser is already provided by tests
1443
- that import base_case.BaseCase from seleniumbase. """
1462
+ that import base_case.BaseCase from seleniumbase. If parameters
1463
+ aren't specified, the method uses the same as the default driver.
1464
+ @Params
1465
+ browser - the browser to use. (Ex: "chrome", "firefox")
1466
+ headless - the option to run webdriver in headless mode
1467
+ servername - if using a Selenium Grid, set the host address here
1468
+ port - if using a Selenium Grid, set the host port here
1469
+ proxy - if using a proxy server, specify the "host:port" combo here
1470
+ switch_to - the option to switch to the new driver (default = True)
1471
+ """
1444
1472
if browser is None :
1445
1473
browser = self .browser
1474
+ browser_name = browser
1446
1475
if headless is None :
1447
1476
headless = self .headless
1448
1477
if servername is None :
1449
1478
servername = self .servername
1450
1479
if port is None :
1451
1480
port = self .port
1452
- if proxy_string is None :
1453
- proxy_string = self .proxy_string
1454
1481
use_grid = False
1455
1482
if servername != "localhost" :
1456
- # Use Selenium Grid (Use --server= 127.0.0.1 for localhost Grid)
1483
+ # Use Selenium Grid (Use " 127.0.0.1" for localhost Grid)
1457
1484
use_grid = True
1485
+ proxy_string = proxy
1486
+ if proxy_string is None :
1487
+ proxy_string = self .proxy_string
1458
1488
valid_browsers = constants .ValidBrowsers .valid_browsers
1459
- if browser not in valid_browsers :
1489
+ if browser_name not in valid_browsers :
1460
1490
raise Exception ("Browser: {%s} is not a valid browser option. "
1461
1491
"Valid options = {%s}" % (browser , valid_browsers ))
1462
- new_driver = browser_launcher .get_driver (browser ,
1463
- headless ,
1464
- use_grid ,
1465
- servername ,
1466
- port ,
1467
- proxy_string )
1468
- self ._extra_drivers .append (new_driver )
1492
+ new_driver = browser_launcher .get_driver (browser_name = browser_name ,
1493
+ headless = headless ,
1494
+ use_grid = use_grid ,
1495
+ servername = servername ,
1496
+ port = port ,
1497
+ proxy_string = proxy_string )
1498
+ self ._drivers_list .append (new_driver )
1499
+ if switch_to :
1500
+ self .driver = new_driver
1469
1501
return new_driver
1470
1502
1503
+ def switch_to_driver (self , driver ):
1504
+ """ Sets self.driver to the specified driver.
1505
+ You may need this if using self.get_new_driver() in your code. """
1506
+ self .driver = driver
1507
+
1508
+ def switch_to_default_driver (self ):
1509
+ """ Sets self.driver to the default/original driver. """
1510
+ self .driver = self ._default_driver
1511
+
1471
1512
############
1472
1513
1473
1514
def _get_new_timeout (self , timeout ):
@@ -1846,6 +1887,16 @@ def setUp(self):
1846
1887
self .servername ,
1847
1888
self .port ,
1848
1889
self .proxy_string )
1890
+ self ._default_driver = self .driver
1891
+ self ._drivers_list .append (self .driver )
1892
+ if self .headless :
1893
+ # Make sure the invisible browser window is big enough
1894
+ try :
1895
+ self .set_window_size (1920 , 1200 )
1896
+ except Exception :
1897
+ # This shouldn't fail, but in case it does, get safely through
1898
+ # setUp() so that WebDrivers can get closed during tearDown().
1899
+ pass
1849
1900
1850
1901
def __insert_test_result (self , state , err ):
1851
1902
data_payload = TestcaseDataPayload ()
@@ -1880,6 +1931,19 @@ def _add_pytest_html_extra(self):
1880
1931
except Exception :
1881
1932
pass
1882
1933
1934
+ def _quit_all_drivers (self ):
1935
+ # Close all open browser windows
1936
+ self ._drivers_list .reverse () # Last In, First Out
1937
+ for driver in self ._drivers_list :
1938
+ try :
1939
+ driver .quit ()
1940
+ except AttributeError :
1941
+ pass
1942
+ except Exception :
1943
+ pass
1944
+ self .driver = None
1945
+ self ._drivers_list = []
1946
+
1883
1947
def tearDown (self ):
1884
1948
"""
1885
1949
Be careful if a subclass of BaseCase overrides setUp()
@@ -1939,20 +2003,8 @@ def tearDown(self):
1939
2003
if self .with_page_source :
1940
2004
log_helper .log_page_source (
1941
2005
test_logpath , self .driver )
1942
- try :
1943
- # Finally close the browser
1944
- if self ._extra_drivers :
1945
- for extra_driver in self ._extra_drivers :
1946
- try :
1947
- extra_driver .quit ()
1948
- except Exception :
1949
- pass # Extra driver was already quit
1950
- self .driver .quit ()
1951
- except AttributeError :
1952
- pass
1953
- except Exception :
1954
- pass
1955
- self .driver = None
2006
+ # (Pytest) Finally close all open browser windows
2007
+ self ._quit_all_drivers ()
1956
2008
if self .headless :
1957
2009
if self .headless_active :
1958
2010
self .display .stop ()
@@ -1990,18 +2042,5 @@ def tearDown(self):
1990
2042
data_payload .logURL = index_file
1991
2043
self .testcase_manager .update_testcase_log_url (data_payload )
1992
2044
else :
1993
- # Using Nosetests
1994
- try :
1995
- # Finally close the browser
1996
- if self ._extra_drivers :
1997
- for extra_driver in self ._extra_drivers :
1998
- try :
1999
- extra_driver .quit ()
2000
- except Exception :
2001
- pass # Extra driver was already quit
2002
- self .driver .quit ()
2003
- except AttributeError :
2004
- pass
2005
- except Exception :
2006
- pass
2007
- self .driver = None
2045
+ # (Nosetests) Finally close all open browser windows
2046
+ self ._quit_all_drivers ()
0 commit comments