pytest and Browserstack

BrowserStack is a cloud-based testing tool that enables developers/testers to test their application across various browsers on different operating systems and mobile devices. We use Browserstack a lot at Qxf2 and recommend it to all our clients. We recently started using pytest to run our tests. We were surprised how quick and easy it was to configure pytest to run our tests on Browserstack. We have decided to share how we were able to do it.


Overview

BrowserStack needs four pieces of information to start a test:
a) the browser
b) the browser version
c) the operating system
d) the operating system version

In this post, we’ll show you how to add these four pieces of information as command line parameters to pytest. While the task at hand is direct, we thought this topic would make a good backdrop for you to learn more about pytest. So throughout this blog post, we have sprinkled in some useful tips that will help you get comfortable with pytest. If you do not understand some of the terms we use – it’s ok! You can still integrate your tests to use pytest and BrowserStack by following the step by step guide and the detailed code samples.


How to configure pytest to work with BrowserStack

pytest can be configured to suit our testing needs. It implements all aspects of configuration, collection, running and reporting. For our problem, there is one term in pytest land that you need to become familiar with – fixtures. A test fixture is simply something that a test must (or may) need to know before it can be executed from a known state. We are going to treat each independent piece of information that BrowserStack requires (e.g.: browser, browser version) as pytest fixtures. Fixtures can be created for the parameters that are being used in the test function. These fixtures can be held in the test file or be held in a special conftest.py file separately. The perk of having fixtures in a conftest.py is that it can be used by my multiple tests.

1. Create a conftest.py file
To begin with, create a file called conftest.py and place it in the root directory of your repository or code base. Your root directory is going to be the directory from which you kick off the py.test command.

2. Add a command line parameter to conftest.py

#Contents of the conftest.py file
def pytest_addoption(parser):
    parser.addoption("-B","--browser",
                      dest="browser",
                      default="firefox",
                      help="Browser. Valid options are firefox, ie and chrome")

3. Add a fixture to conftest.py

@pytest.fixture
def browser():
    "pytest fixture for browser"
    return pytest.config.getoption("-B") #Note how this ties to the newly added command line parameter

Everytime pytest sees browser as the test function parameter it executes the pytest fixture which looks if any command line parameter has been provided, if no option is given pytest uses the default option that was mentioned when the option was added.

We are almost done! Once you setup your conftest.py to take in the browser version, os and os version – you are done with configuring pytest. You can see the completed conftest file (has fixtures for all four pieces of information that BrowserStack needs) in the ‘Putting it all together section’.


How to run a test on Browserstack

In this section we will show you how to modify your test so it works well with BrowserStack and pytest. Let us try running an example test to check the browser title and test the form in the Qxf2-selenium-tutorial-page on Browserstack using pytest.

If you are completely new to BrowserStack, you can get started with this post. For the sake of completeness, we will show you a snippet required to get a webdriver and set useful capabilities:

#NOTE: This is highly simplified code to make this post illustrative
#We do not use this code at clients
#We use Driver_Factory to return apporpriate drivers within our framework
def get_webdriver(browser,browser_version,platform,os_version):
    "Run the test in browser stack browser stack flag is 'Y'"
    USERNAME = usename #We fetch values from a conf file in our framework we use on our clients
    PASSWORD = accesskey
    if browser.lower() == 'firefox':
        desired_capabilities = DesiredCapabilities.FIREFOX
    if browser.lower() == 'chrome':
        desired_capabilities = DesiredCapabilities.CHROME
    desired_capabilities['os'] = platform
    desired_capabilities['os_version'] = os_version
    desired_capabilities['browser_version'] = browser_version
 
    return webdriver.Remote(command_executor='http://%s:%[email protected]:80/wd/hub'%(USERNAME,PASSWORD),
                            desired_capabilities=desired_capabilities)

The get_webdriver method gets the browser,browser_version,platform,os_version sets them as the desired capabilities and returns the appropriate webdriver.


Putting it all together:

We are including a sample test for you to checkout the pytest and BrowserStack integration. The test script looks like the code below:

#NOTE: This is highly simplified code to make this post illustrative
#We do not use this code at clients
#Our framework uses the Page Object pattern
 
#Contents of test_example_form.py
def test_example_form(browser,browserstack_flag,browser_version,platform,os_version):
    "Test example form"
 
    #Create an driver object
    driver = get_webdriver(browser,browser_version,platform,os_version)
    #Create variables to keep count of pass/fail
    pass_check_counter = 0
    total_checks = 0
    #Visit the tutorial page
    driver.get('http://qxf2.com/selenium-tutorial-main') 
    print "The browser for this test it %s"%browser
    print "The browser version is %s"%browser_version
    print "The platform is %s"%platform
    print "The os version is %s"%os_version
    #Check 1: Is the page title correct?
    if(driver.title=="Qxf2 Services: Selenium training main"):
        print "\n"
        print ("Success: Title of the Qxf2 Tutorial page is correct")
        pass_check_counter += 1
    else:
        print ("Failed: Qxf2 Tutorial page Title is incorrect")
    total_checks += 1 
    #Check 2: Fill name, email and phone in the example form
    total_checks += 1
    name_field = driver.find_element_by_xpath("//input[@type='name']")
    name_field.send_keys('Shivahari')
    email_field = driver.find_element_by_xpath("//input[@type='email']")
    email_field.send_keys('[email protected]')
    phone_field = driver.find_element_by_xpath("//input[@type='phone']")
    phone_field.send_keys('9999999999')
    submit_button = driver.find_element_by_xpath("//button[@type='submit']") #Click on the Click me button
    try:
        submit_button.click()
        pass_check_counter += 1
    except Exception,e:
        print str(e)   
    #Quit the browser window
    driver.quit() 
    #Assert if the pass and fail check counters are equal
    assert total_checks == pass_check_counter

The completed conftest.py looks like this:

#Contents of conftest.py
import pytest
import os
 
@pytest.fixture
def browser():
    "pytest fixture for browser"
    return pytest.config.getoption("-B")
 
 
@pytest.fixture
def browserstack_flag():
    "pytest fixture for browserstack flag"
    return pytest.config.getoption("-M")
 
 
@pytest.fixture
def browser_version():
    "pytest fixture for browser version"
    return pytest.config.getoption("-V") 
 
 
@pytest.fixture
def platform():
    "pytest fixture for platform"
    return pytest.config.getoption("-P") 
 
 
@pytest.fixture
def os_version():
    "pytest fixture for os version"
    return pytest.config.getoption("-O") 
 
 
def pytest_addoption(parser):
    parser.addoption("-B","--browser",
                      dest="browser",
                      default="firefox",
                      help="Browser. Valid options are firefox, ie and chrome") 
    parser.addoption("-M","--browserstack_flag",
                      dest="browserstack_flag",
                      default="N",
                      help="Run the test in Browserstack: Y or N")
    parser.addoption("-V","--ver",
                      dest="browser_version",
                      help="The version of the browser: a whole number",
                      default=45)
    parser.addoption("-P","--platform",
                      dest="platform",
                      help="The operating system: Windows 7, Linux",
                      default="Windows")
    parser.addoption("-O","--os_version",
                      dest="os_version",
                      help="The operating system: xp, 7",
                      default="7")

Run the test:

To run the test use the command py.test
pytest_test_run2
You can run this test on a different platform (say OS X Yosemite) using a different browser (say Chrome 50) by using the command:
py.test -B chrome -V 50 -P "OS X" -O Yosemite -M y


There you go,a detailed example to configure pytest and run tests on browserstack. Now try running the tests across different platforms,platform version,browsers and browser versions.

If you liked what you read, know more about Qxf2.


Subscribe to our weekly Newsletter


View a sample



Leave a Reply

Your email address will not be published. Required fields are marked *