Selenium and Python

Applies to CrossBrowserTesting SaaS, last modified on October 22, 2021

Get started with Selenium and Python

Selenium is a great tool to automate our functional tests on websites and web applications in our favorite language. With CrossBrowserTesting, you can use Selenium and Python to run automated browser tests on thousands of real mobile and desktop browsers in the cloud. To learn more about the Selenium API, we recommend you read Selenium’s documentation which can be found here.

Note: You will need a Username and Authkey to run your tests on CrossBrowserTesting To get yours, sign up for a free trial or purchase a plan.

Install Selenium

To get started, make sure you have Selenium's language bindings for Python installed and ready. If you have pip, run the following command in your terminal:

sudo pip install selenium

CrossBrowserTesting also recommends requests for RESTful API calls in python. You can install it using pip with following command in your terminal:

sudo pip install requests

And you can follow the easy setup instructions in the requests documentation.

If you are new to Unit-testing and you would like to know more about Python's module as used below we recommend the following documentation: https://docs.python.org/2.7/library/unittest.html

Run your first test

Once you have everything ready, let's try running our first automated test with CrossBrowserTesting! Copy and paste the following code into your text editor of choice, and try running it from the terminal:

import unittest
from selenium import webdriver
import requests

class SeleniumCBT(unittest.TestCase):
    def setUp(self):

        self.username = "user@email.com"
        self.authkey = "12345"

        self.api_session = requests.Session()
        self.api_session.auth = (self.username,self.authkey)
        self.test_result = None

        caps = {}
        caps['browserName'] = 'Chrome'
        caps['version'] = '60x64'
        caps['platform'] = 'Windows 10'
        caps['screenResolution'] = '1366x768'
        caps['record_video'] = 'true'

        self.driver = webdriver.Remote(
            desired_capabilities=caps,
            command_executor="http://%s:%s@hub.crossbrowsertesting.com:80/wd/hub"%(self.username,self.authkey)
        )

        self.driver.implicitly_wait(20)

    def test_CBT(self):
            self.driver.get('http://crossbrowsertesting.github.io/selenium_example_page.html')
            self.assertEqual("Selenium Test Example Page", self.driver.title)
            self.test_result = 'pass'
            self.driver.quit()
       

if __name__ == '__main__':
    unittest.main()

Our test passed! You can now run your first Selenium test with Python on CrossBrowserTesting’s platform.

Test capabilities

CrossBrowserTesting allows you to add certain capabilities to your test, like video recordings, naming structure and more.

Name tests

Naming your tests can help organize your automated test cases for easier debugging. You can also mark Build number to denote releases.

caps['name'] = 'Selenium Test Example'

caps['build'] = '1.0'

Choose browsers

To choose your environment, you can select from Browsers, Operating System, Resolutions, and Devices. You can use our easy Selenium Wizard to select your configuration or hit our browser list endpoint.

caps['browserName'] = 'Chrome'

Real device testing

You can run your Selenium tests against real mobile browsers by setting a few unique capabilities.

caps['browserName'] = 'Chrome'
caps['deviceName'] = 'Nexus 6P'
caps['platformVersion'] = '7.0'
caps['platformName'] = 'Android'
caps['deviceOrientation'] = 'portrait'

Record videos

For superior debugging capabilities, CrossBrowserTesting offers the ability to record a video of your Selenium test session. You can find a copy of your test results here.

caps['record_video'] = 'true'

Record network

To record the network packets during your test for performance debugging, set the following to "true".

caps['record_network'] = 'true'

Run a local test

With our Local Tunnel, you can run a test on a local URL or behind your company's firewall. There are two different ways to connect the CrossBrowserTesting local tunnel: our Node.js client and our Chrome Extension.

You can read more about setting up, starting, and using your tunnel connection here.

Note: When a tunnel is open, any automated test can access websites locally, behind a firewall, or across a proxy. There is no need to set a capability during your test.

Run tests in parallel

To speed your automated testing, you can run your tests in parallel, making use of several browsers or devices at one time. To run parallel tests in Python we'll make use of the queue dependency.

from queue import Queue
from threading import Thread
from selenium import webdriver
import time

USERNAME = "user@email.com"
API_KEY = "12345"

q = Queue(maxsize=0)

browsers = [
  {"os_api_name": "Win7x64-C2", "browser_api_name": "IE10", "name": "Python Parallel"},
  {"os_api_name": "Win8.1", "browser_api_name": "Chrome43x64", "name": "Python Parallel"},
]

# put all of the browsers into the queue before pooling workers
for browser in browsers:
    q.put(browser)

num_threads = 10

def test_runner(q):
    while q.empty() is False:
        try:
            browser = q.get()
            print("%s: Starting" % browser["browser_api_name"])
            driver = webdriver.Remote(desired_capabilities=browser, command_executor="http://%s:%s@hub.crossbrowsertesting.com:80/wd/hub" % (USERNAME, API_KEY) )
            print("%s: Getting page" % browser["browser_api_name"])
            driver.get("http://crossbrowsertesting.com")
            print("%s: Quitting browser and ending test" % browser["browser_api_name"])
        except:
            print("%s: Error" % browser["browser_api_name"])
        finally:
            driver.quit()
            time.sleep(15)
            q.task_done()


for i in range(num_threads):
    worker = Thread(target=test_runner, args=(q,))
    worker.setDaemon(True)
    worker.start()

q.join()

Take snapshots

You can take snapshots of errors during your test run for easy debugging and documentation. You can share these snapshots through Jira, Slack, or Email. To take a snapshot during your test run, you just have to invoke our API.

snapshot_hash = self.api_session.post('https://crossbrowsertesting.com/api/v3/selenium/' + self.driver.session_id + '/snapshots').json()['hash']

Here is a full example:

import unittest
from selenium import webdriver
import requests
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

class LoginForm(unittest.TestCase):
    def setUp(self):

        # Put your username and authey below
        # You can find your authkey at crossbrowsertesting.com/account
        self.username = "user@email.com"
        self.authkey = "12345"

        self.api_session = requests.Session()
        self.api_session.auth = (self.username,self.authkey)

        self.test_result = None

        caps = {}

        caps['name'] = 'Screenshot Example'
        caps['browser_api_name'] = 'Chrome53'
        caps['os_api_name'] = 'Win10'
        caps['screen_resolution'] = '1024x768'


        self.driver = webdriver.Remote(
            desired_capabilities=caps,
            command_executor="http://%s:%s@hub.crossbrowsertesting.com:80/wd/hub"%(self.username,self.authkey)
        )

        self.driver.implicitly_wait(20)

    def test_CBT(self):
    
        try:
            self.driver.get('http://crossbrowsertesting.github.io/login-form.html')
            self.driver.maximize_window()
            self.driver.find_element_by_name('username').send_keys('tester@crossbrowsertesting.com')
            self.driver.find_element_by_name('password').send_keys('test123')
            self.driver.find_element_by_css_selector('body > div > div > div > div > form > div.form-actions > button').click()

            elem = WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.XPATH, '//*[@id=\"logged-in-message\"]/h2'))
            )

            welcomeText = elem.text
            self.assertEqual("Welcome tester@crossbrowsertesting.com", welcomeText)

            print("Taking snapshot")
            snapshot_hash = self.api_session.post('https://crossbrowsertesting.com/api/v3/selenium/' + self.driver.session_id + '/snapshots').json()['hash']

            self.test_result = 'pass'

        except AssertionError as e:
            # log the error message, and set the score to "during tearDown()".
            self.api_session.put('https://crossbrowsertesting.com/api/v3/selenium/' + self.driver.session_id + '/snapshots/' + snapshot_hash,
                data={'description':"AssertionError: " + str(e)})
            self.test_result = 'fail'
            raise

    def tearDown(self):
        print("Done with session %s" % self.driver.session_id)
        self.driver.quit()
        # Here we make the api call to set the test's score.
        # Pass it it passes, fail if an assertion fails, unset if the test didn't finish
        if self.test_result is not None:
            self.api_session.put('https://crossbrowsertesting.com/api/v3/selenium/' + self.driver.session_id,
                data={'action':'set_score', 'score':self.test_result})


if __name__ == '__main__':
    unittest.main()

Troubleshooting

Make the browser wait

One of the most common errors in Selenium is caused by a page not being fully loaded before making assertions crucial to the passing or failing score of your test. Selenium provides two basic ways of performing waits that force your test to pause before continuing the next in a sequence of steps. This will help prevent that pesky ElementNotVisibleException that causes so many false negatives.

Selenium divides waits into explicit and implicit categories. Explicit waits pause test execution until a certain condition has been met. In order to successfully perform an explicit wait, we must instantiate an Explicit Wait object. The following snippet provides the basis for an explicit wait:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as expected

driver = webdriver.Remote(
            desired_capabilities=caps,
            command_executor="http://%s:%s@hub.crossbrowsertesting.com:80/wd/hub"%         (self.username,self.authkey)
        )

driver.get("www.crossbrowsertesting.com")
try:
    elem = WebDriverWait(driver, 10).until(
        expected.title_is('CrossBrowserTesting App')
    )
finally:
    driver.quit()

An implicit wait pauses the test for a set amount of time until it is expected that a given condition will already true. The following code snippet makes use of the implicit wait method of WebDriver before making an assertion in regard to the title of the web page.

from selenium import web driver

driver = webdriver.Remote(
            desired_capabilities=caps,
            command_executor="http://%s:%s@hub.crossbrowsertesting.com:80/wd/hub"%         (self.username,self.authkey)
        )

driver.get("www.crossbrowsertesting.com")
driver.implicitly_wait(5)             # wait 5 seconds
assertEqual(driver.title, "CrossBrowser Testing App")

See Also

Selenium

Highlight search results