The Sauce Labs Cookbook

Sauce Headless

Front End Performance Testing

Insights

External Resources

More Info


Page tree
Skip to end of metadata
Go to start of metadata

These examples use the pytest test framework to run tests on real devices. Feel free to clone these scripts directly from GitHub, and follow the instructions in the README file.

Python Config

This script initializes the test fixtures, as well as the prerequisite and post-requisite test tasks.

 conftest.py

import pytest
import os
import json
import re

from appium import webdriver


def pytest_addoption(parser):
    parser.addoption("--dc", action="store", default='us', help="Set Sauce Labs Data Center (US or EU)")


@pytest.fixture
def data_center(request):
    return request.config.getoption('--dc')


@pytest.fixture
def ios_up_driver(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'iPhone.*',
        'platformName': 'iOS',
        'name': request.node.name,
        'app': 'storage:filename=iOS.RealDevice.SauceLabs.Mobile.Sample.app.2.2.1.ipa'
    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = "http://ondemand.eu-central-1.saucelabs.com/wd/hub"
    else:   
        sauce_url = "http://ondemand.us-west-1.saucelabs.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()


@pytest.fixture
def ios_simulator(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'iPhone XS Simulator',
        'appiumVersion': '1.17.1',
        'platformName': 'iOS',
        'platformVersion': "13.4",
        'deviceOrientation': "portrait",
        'name': request.node.name,
        'app': 'storage:filename=iOS.Simulator.SauceLabs.Mobile.Sample.app.2.7.0.zip'
    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = "http://ondemand.eu-central-1.saucelabs.com/wd/hub"
    else:   
        sauce_url = "http://ondemand.us-west-1.saucelabs.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()


@pytest.fixture
def ios_to_driver(request, data_center):
    
    caps = {
        'platformName':     'iOS',
        'deviceOrientation':'portrait',
        'privateDevicesOnly': False, 
        'phoneOnly': True
    }

    rdc_key = os.environ['TESTOBJECT_SAMPLE_IOS']
    caps['testobject_api_key'] = rdc_key
    test_name = request.node.name
    caps['name'] = test_name

    if data_center and data_center.lower() == 'eu':
        sauce_url = "http://appium.testobject.com/wd/hub"
    else:   
        sauce_url = "http://us1.appium.testobject.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    
    # This is specifically for SauceLabs plugin.
    # In case test fails after selenium session creation having this here will help track it down.
    # creates one file per test non ideal but xdist is awful
    if driver:
        print("SauceOnDemandSessionID={} job-name={}\n".format(driver.session_id, test_name))
    else:
        raise WebDriverException("Never created!")

    yield driver
    
    driver.quit()


@pytest.fixture
def android_to_driver(request, data_center):
    
    caps = {
        'deviceName': 'Google.*',
        'platformName': 'Android',
        'deviceOrientation':'portrait',
        'privateDevicesOnly': False 
    }

    rdc_key = os.environ['TESTOBJECT_SAMPLE_ANDROID']
    caps['testobject_api_key'] = rdc_key
    test_name = request.node.name
    caps['name'] = test_name

    if data_center and data_center().lower() == 'eu':
        sauce_url = "http://appium.testobject.com/wd/hub"
    else:   
        sauce_url = "http://us1.appium.testobject.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    
    # This is specifically for SauceLabs plugin.
    # In case test fails after selenium session creation having this here will help track it down.
    # creates one file per test non ideal but xdist is awful
    if driver:
        print("SauceOnDemandSessionID={} job-name={}\n".format(driver.session_id, test_name))
    else:
        raise WebDriverException("Never created!")

    yield driver
    
    driver.quit()


@pytest.fixture
def android_up_driver(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'Google.*',
        'platformName': 'Android',
        'name': request.node.name,
        'app': 'storage:filename=Android.SauceLabs.Mobile.Sample.app.2.3.0.apk'
    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = 'http://ondemand.eu-central-1.saucelabs.com/wd/hub'
    else:
        sauce_url = 'http://ondemand.us-west-1.saucelabs.com/wd/hub'

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()


@pytest.fixture
def android_emulator(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'Android GoogleAPI Emulator',
        'platformName': 'Android',
        'platformVersion': '10.0',
        'deviceOrientation': 'portrait',
        'name': request.node.name,
        'appiumVersion': '1.17.1',
        'appWaitActivity': 'com.swaglabsmobileapp.MainActivity',
        'app': 'storage:filename=Android.SauceLabs.Mobile.Sample.app.2.3.0.apk'

    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = 'http://ondemand.eu-central-1.saucelabs.com/wd/hub'
    else:
        sauce_url = 'http://ondemand.us-west-1.saucelabs.com/wd/hub'

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()

Test Objects

These scripts represents the individual test. Click below to see the script(s):

 test_add_to_cart.py

import pytest


def test_add_to_cart(emusim_driver):
    emusim_driver.get('https://www.saucedemo.com/inventory.html')
    emusim_driver.find_element_by_class_name('btn_primary').click()

    assert emusim_driver.find_element_by_class_name('shopping_cart_badge').text == '1'

    emusim_driver.get('https://www.saucedemo.com/cart.html')
    expected = emusim_driver.find_elements_by_class_name('inventory_item_name')
    assert len(expected) == 1

def test_add_two_to_cart(emusim_driver):
    emusim_driver.get('https://www.saucedemo.com/inventory.html')
    emusim_driver.find_element_by_class_name('btn_primary').click()
    emusim_driver.find_element_by_class_name('btn_primary').click()

    assert emusim_driver.find_element_by_class_name('shopping_cart_badge').text == '2'

    emusim_driver.get('https://www.saucedemo.com/cart.html')
    expected = emusim_driver.find_elements_by_class_name('inventory_item_name')
    assert len(expected) == 2

 test_login_fail.py

import pytest


def test_valid_crentials_login(emusim_driver):
    emusim_driver.get('https://www.saucedemo.com')

    emusim_driver.find_element_by_id('user-name').send_keys('locked_out_user')
    emusim_driver.find_element_by_id('password').send_keys('secret_sauce')
    emusim_driver.find_element_by_css_selector('.btn_action').click()

    assert emusim_driver.find_element_by_css_selector('.error-button').is_displayed()

 test_login_success.py

import pytest


def test_valid_crentials_login(emusim_driver):
    emusim_driver.get('https://www.saucedemo.com')

    emusim_driver.find_element_by_id('user-name').send_keys('standard_user')
    emusim_driver.find_element_by_id('password').send_keys('secret_sauce')
    emusim_driver.find_element_by_css_selector('.btn_action').click()

    assert "/inventory.html" in emusim_driver.current_url

Python Config

This script initializes the test fixtures, as well as the prerequisite and post-requisite test tasks.

 conftest.py

import pytest
import os
import json
import re

from appium import webdriver


def pytest_addoption(parser):
    parser.addoption("--dc", action="store", default='us', help="Set Sauce Labs Data Center (US or EU)")


@pytest.fixture
def data_center(request):
    return request.config.getoption('--dc')


@pytest.fixture
def ios_up_driver(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'iPhone.*',
        'platformName': 'iOS',
        'name': request.node.name,
        'app': 'storage:filename=iOS.RealDevice.SauceLabs.Mobile.Sample.app.2.2.1.ipa'
    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = "http://ondemand.eu-central-1.saucelabs.com/wd/hub"
    else:   
        sauce_url = "http://ondemand.us-west-1.saucelabs.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()


@pytest.fixture
def ios_simulator(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'iPhone XS Simulator',
        'appiumVersion': '1.17.1',
        'platformName': 'iOS',
        'platformVersion': "13.4",
        'deviceOrientation': "portrait",
        'name': request.node.name,
        'app': 'storage:filename=iOS.Simulator.SauceLabs.Mobile.Sample.app.2.7.0.zip'
    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = "http://ondemand.eu-central-1.saucelabs.com/wd/hub"
    else:   
        sauce_url = "http://ondemand.us-west-1.saucelabs.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()


@pytest.fixture
def ios_to_driver(request, data_center):
    
    caps = {
        'platformName':     'iOS',
        'deviceOrientation':'portrait',
        'privateDevicesOnly': False, 
        'phoneOnly': True
    }

    rdc_key = os.environ['TESTOBJECT_SAMPLE_IOS']
    caps['testobject_api_key'] = rdc_key
    test_name = request.node.name
    caps['name'] = test_name

    if data_center and data_center.lower() == 'eu':
        sauce_url = "http://appium.testobject.com/wd/hub"
    else:   
        sauce_url = "http://us1.appium.testobject.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    
    # This is specifically for SauceLabs plugin.
    # In case test fails after selenium session creation having this here will help track it down.
    # creates one file per test non ideal but xdist is awful
    if driver:
        print("SauceOnDemandSessionID={} job-name={}\n".format(driver.session_id, test_name))
    else:
        raise WebDriverException("Never created!")

    yield driver
    
    driver.quit()


@pytest.fixture
def android_to_driver(request, data_center):
    
    caps = {
        'deviceName': 'Google.*',
        'platformName': 'Android',
        'deviceOrientation':'portrait',
        'privateDevicesOnly': False 
    }

    rdc_key = os.environ['TESTOBJECT_SAMPLE_ANDROID']
    caps['testobject_api_key'] = rdc_key
    test_name = request.node.name
    caps['name'] = test_name

    if data_center and data_center().lower() == 'eu':
        sauce_url = "http://appium.testobject.com/wd/hub"
    else:   
        sauce_url = "http://us1.appium.testobject.com/wd/hub"

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    
    # This is specifically for SauceLabs plugin.
    # In case test fails after selenium session creation having this here will help track it down.
    # creates one file per test non ideal but xdist is awful
    if driver:
        print("SauceOnDemandSessionID={} job-name={}\n".format(driver.session_id, test_name))
    else:
        raise WebDriverException("Never created!")

    yield driver
    
    driver.quit()


@pytest.fixture
def android_up_driver(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'Google.*',
        'platformName': 'Android',
        'name': request.node.name,
        'app': 'storage:filename=Android.SauceLabs.Mobile.Sample.app.2.3.0.apk'
    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = 'http://ondemand.eu-central-1.saucelabs.com/wd/hub'
    else:
        sauce_url = 'http://ondemand.us-west-1.saucelabs.com/wd/hub'

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()


@pytest.fixture
def android_emulator(request, data_center):
    caps = {
        'username': os.environ['SAUCE_USERNAME'],
        'accessKey': os.environ['SAUCE_ACCESS_KEY'],
        'deviceName': 'Android GoogleAPI Emulator',
        'platformName': 'Android',
        'platformVersion': '10.0',
        'deviceOrientation': 'portrait',
        'name': request.node.name,
        'appiumVersion': '1.17.1',
        'appWaitActivity': 'com.swaglabsmobileapp.MainActivity',
        'app': 'storage:filename=Android.SauceLabs.Mobile.Sample.app.2.3.0.apk'

    }

    if data_center and data_center.lower() == 'eu':
        sauce_url = 'http://ondemand.eu-central-1.saucelabs.com/wd/hub'
    else:
        sauce_url = 'http://ondemand.us-west-1.saucelabs.com/wd/hub'

    driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
    yield driver
    driver.quit()

Test Objects

These scripts represents the individual tests. Click below to see the script:

 test_invalid_login.py

def test_blank_credentials(ios_up_driver):
    ios_up_driver.find_element_by_accessibility_id("test-Username").send_keys("")
    ios_up_driver.find_element_by_accessibility_id("test-Password").send_keys("")
    ios_up_driver.find_element_by_accessibility_id("test-LOGIN").click()

    assert ios_up_driver.find_element_by_accessibility_id("test-Error message").is_displayed()

 test_valid_login.py

def test_standard_user(ios_up_driver):
    ios_up_driver.find_element_by_accessibility_id("test-Username").send_keys("standard_user")
    ios_up_driver.find_element_by_accessibility_id("test-Password").send_keys("secret_sauce")
    ios_up_driver.find_element_by_accessibility_id("test-LOGIN").click()

    assert ios_up_driver.find_element_by_accessibility_id("test-PRODUCTS").is_displayed()