Skip to end of metadata
Go to start of metadata

Sauce Labs is a cloud platform for executing automated and manual mobile and web tests. Sauce Labs supports running automated tests with Selenium WebDriver (for web applications) and Appium (for native and mobile web applications). This topic will provide you with basic information and code examples to get your Python tests up and running with Sauce.

Example Only

The code in this topic is presented as an example only, since your tests and testing environments may require specialized scripting. This information should be taken only as an illustration of how you could set up your tests with Sauce Labs, and is not directly supported by Sauce.

Prerequisites

Before getting started, you should read the Best Practices for Running Tests.
  • You will need to install the Selenium WebDriver client driver to your local Python environment
    You can either download the driver from the link, or use pip to install it.

    pip install selenium
  • You should also install the Sauce Python client, which provides features for reporting job information to the Sauce Labs dashboard. 

    pip install sauceclient

Quick Start

If you wanted to run Selenium locally, you might initiate a driver for the browser that you want to test on like so:
Running a Local Python Test
driver = webdriver.Firefox() 

If you wanted to run on Sauce, you would instead use webdriver.Remote(), and then pass it two parameters: command_executor, which points to the Sauce cloud and uses your Sauce Labs authentication to log in, and desired_capabilties, which specifies the browsers and operating systems to run the tests against.

Running a Python Test Remotely on Sauce
# this is how you set up a test to run on Sauce Labs
desired_cap = {
    'platform': "Mac OS X 10.9",
    'browserName': "chrome",
    'version': "31",
}
username = os.environ['SAUCE_USERNAME']
access_key = os.environ['SAUCE_ACCESS_KEY']
driver = webdriver.Remote(
    command_executor='https://{}:{}@ondemand.saucelabs.com/wd/hub'.format(username, access_key),
    desired_capabilities=desired_cap)

You can use the Platform Configurator to specify the desired capabilities for any browser/platform combination you want. 

Code Sample

This simple Python test script tests the Google front page. Despite its simplicity, it contains everything you need to know in order to run an automated test on Sauce Labs.

You can also clone this script from GitHub.

""" Simple Selenium tests """
import os

# Selenium 3.14+ doesn't enable certificate checking
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

# This is the only code you need to edit in your existing scripts.
# The command_executor tells the test to run on Sauce, while the desired_capabilities
# parameter tells us which browsers and OS to spin up.
desired_cap = {
    'platform': "Mac OS X 10.12",
    'browserName': "chrome",
    'version': "latest",
}
username = os.environ['SAUCE_USERNAME']
access_key = os.environ['SAUCE_ACCESS_KEY']
driver = webdriver.Remote(
   command_executor='https://{}:{}@ondemand.saucelabs.com/wd/hub'.format(username, access_key),
   desired_capabilities=desired_cap)

# This is your test logic. You can add multiple tests here.
driver.get("http://www.google.com")

if "Google" not in driver.title:
    raise Exception("Unable to load google page!")
elem = driver.find_element_by_name("q")
elem.send_keys("Sauce Labs")
elem.send_keys(Keys.TAB)
elem.submit()
assert "Sauce" in driver.title

# This is where you tell Sauce Labs to stop running tests on your behalf.
# It's important so that you aren't billed after your test finishes.
driver.quit()

This code sample is more complex, and relies on some libraries that you may need to install to make it work. 

A More Complex Python Code Example
import os
import sys
import new
import unittest
from selenium import webdriver
from sauceclient import SauceClient
# it's best to remove the hardcoded defaults and always get these values
# from environment variables
USERNAME = os.environ['SAUCE_USERNAME']
ACCESS_KEY = os.environ['SAUCE_ACCESS_KEY']
sauce = SauceClient(USERNAME, ACCESS_KEY)
browsers = [{"platform": "Mac OS X 10.9",
             "browserName": "chrome",
             "version": "31"},
            {"platform": "Windows 8.1",
             "browserName": "internet explorer",
             "version": "11"}]

def on_platforms(platforms):
    def decorator(base_class):
        module = sys.modules[base_class.__module__].__dict__
        for i, platform in enumerate(platforms):
            d = dict(base_class.__dict__)
            d['desired_capabilities'] = platform
            name = "%s_%s" % (base_class.__name__, i + 1)
            module[name] = new.classobj(name, (base_class,), d)
    return decorator

@on_platforms(browsers)
class SauceSampleTest(unittest.TestCase):
    def setUp(self):
        self.desired_capabilities['name'] = self.id()
        sauce_url = "http://%s:%s@ondemand.saucelabs.com:80/wd/hub"
        self.driver = webdriver.Remote(
            desired_capabilities=self.desired_capabilities,
            command_executor=sauce_url % (USERNAME, ACCESS_KEY)
        )
    def test_sauce(self):
        self.driver.get('http://saucelabs.com/test/guinea-pig')
        assert "I am a page title - Sauce Labs" in self.driver.title
        comments = self.driver.find_element_by_id('comments')
        comments.send_keys('Hello! I am some example comments.'
                           ' I should be in the page after submitting the form')
        self.driver.find_element_by_id('submit').click()
        commented = self.driver.find_element_by_id('your_comments')
        assert ('Your comments: Hello! I am some example comments.'
                ' I should be in the page after submitting the form'
                in commented.text)
        body = self.driver.find_element_by_xpath('//body')
        assert 'I am some other page content' not in body.text
        self.driver.find_elements_by_link_text('i am a link')[0].click()
        body = self.driver.find_element_by_xpath('//body')
        assert 'I am some other page content' in body.text
    def tearDown(self):
        print("Link to your job: https://saucelabs.com/jobs/%s" % self.driver.session_id)
        try:
            if sys.exc_info() == (None, None, None):
                sauce.jobs.update_job(self.driver.session_id, passed=True)
            else:
                sauce.jobs.update_job(self.driver.session_id, passed=False)
        finally:
            self.driver.quit() 

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

Running Local Tests

Developing websites/apps within your local network is secure and efficient. The drawback to this method is that local assets are not publicly-accessible on the Internet, so the browsers/devices in the Sauce Labs cloud can't load and test your app. The solution is to use Sauce ConnectSauce Connect is a proxy server that creates a secure tunnel connection between the Sauce Labs virtual machine that runs your test and your local  network. You can also use Sauce Connect to test applications and websites that are located within your corporate firewall. Sauce Connect is not required to run tests on Sauce Labs, only in situations where the application or website you want to test is not publicly accessible. 

Running Tests in Parallel

Now that you’re running tests on Sauce, you may wonder how you can run your tests faster. One way to increase speed is by running tests in parallel across multiple virtual machines.

You can run your tests in parallel at two levels, and you can run your tests in parallel across multiple browsers. For example, if you have 10 tests and want to run on five browsers, this would be parallelism of five. You can also run tests across browsers and each test in parallel. Using our previous example this would be more like 50 parallel tests. Doing this requires that your tests are written in a way that they do not collide with one another, as described in our Best Practice topics avoiding external test dependencies and avoiding dependencies between tests.

Match Thread Count to Concurrency Limit

You should match your thread count to your concurrency limit, which is shown in the My Account section of your user profile information on the Sauce Labs dashboard.  

For more information, check out the example scripts in our GitHub repo

Reporting on Test Results

"Wait," you might be asking, "My test says 'Complete' but what happens if it fails?"

Unfortunately, Sauce has no way to determine whether your test passed or failed automatically, since it is determined entirely by your business logic. You can, however, tell Sauce about the results of our tests automatically using the Sauce python client and adding these lines to your test. 

# this authenticates you 
from sauceclient import SauceClient
sauce_client = SauceClient("YOUR_SAUCE_USERNAME", "YOUR_SAUCE_ACCESSKEY")

# this belongs in your test logic
sauce_client.jobs.update_job(driver.session_id, passed=True) 

You should also follow our recommended best practice of adding build numbers, tags, and other identifying information to your tests so you can easily find and manage them in your test results and archives pages