Run automation tests on LambdaTest using pytest

Qxf2 has been using popular cross-browser tools like BrowserStack and Sauce Labs for long. Recently, we integrated the LambdaTest tool also with our Page Object Model Framework. So we thought to write about it.

In this post, we will guide you through the process of running automation tests on LambdaTest using pytest. We will cover everything from setting up your LambdaTest account, configuring your test environment, writing automated test with pytest and running these tests on LambdaTest. By the end of this post, you will have a clear understanding of how to leverage LambdaTest for executing cross-browser tests efficiently and effectively.


How to run automation test on LambdaTest:

To run automation tests on LambdaTest, you need to follow below steps:
1) Register on LambdaTest and get accesskey
2) Configure pytest
3) Get LambdaTest webdriver
4) Write a simple test to run on LambdaTest
5) Run test on LambdaTest


Register on LambdaTest and get accesskey:

Navigate to LambdaTest and Sign up. Once you successfully open your account, log in to your account. Go to “Settings” > “Account Settings” > “Password and Security” and get your access key and username. This username and access_key is required for running tests on LambdaTest. We need it in upcoming section.


Configure pytest:

To run tests on LambdaTest, we need to provide below information:
1. os_name
2. os_version
3. browser
4. browser_version
5. remote_project_name
6. remote_build_name

Good to pass the above information as a command line parameter to pytest as we need to keep on changing this value as per our need. To add a command line parameter to pytest, we need to add a pytest option and a fixture to tie the option with it under conftest.py. Create or update conftest.py with the following lines of code for each option.

@pytest.fixture
def browser(request):
    "pytest fixture for browser"
    return request.config.getoption("--browser")
 
def pytest_addoption(parser):
    "Method to add the option to ini."
    try:
        parser.addoption("--browser",
                            dest="browser",
                            default="chrome",
                            help="Browser. Valid options are firefox, ie and chrome")
 
    except Exception as e:
        print("Exception when trying to run test: %s"%__file__)
        print("Python says:%s"%str(e))

Similarly, you can write command line options for browser_version, os_name, os_version, remote_project_name and remote_project_build.

Look at the complete conftest.py file below:
Note: This is highly simplified code to make this post illustrative. We do not use this quality of the code at clients.

#Content on conftest.py
import pytest
 
@pytest.fixture
def browser(request):
    "pytest fixture for browser"
    return request.config.getoption("--browser")
 
@pytest.fixture
def browser_version(request):
    "pytest fixture for browser version"
    return request.config.getoption("--ver")
 
@pytest.fixture
def os_name(request):
    "pytest fixture for os_name"
    return request.config.getoption("--os_name")
 
@pytest.fixture
def os_version(request):
    "pytest fixture for os version"
    return request.config.getoption("--os_version")
 
@pytest.fixture
def remote_project_name(request):
    "pytest fixture for project name"
    return request.config.getoption("--remote_project_name")
 
@pytest.fixture
def remote_build_name(request):
    "pytest fixture for build name"
    return request.config.getoption("--remote_build_name")
 
@pytest.fixture
def testname(request):
    "pytest fixture for testname"
    name_of_test = request.node.name
    name_of_test = name_of_test.split('[')[0]
 
    return name_of_test
 
def pytest_addoption(parser):
    "Method to add the option to ini."
    try:
        parser.addoption("--browser",
                            dest="browser",
                            default="chrome",
                            help="Browser. Valid options are firefox, ie and chrome")
        parser.addoption("--ver",
                            dest="browser_version",
                            help="The version of the browser: a whole number",
                            default="125")
        parser.addoption("--os_name",
                            dest="os_name",
                            help="The operating system: Windows, Linux",
                            default="Windows")
        parser.addoption("--os_version",
                            dest="os_version",
                            help="The operating system: xp, 7",
                            default="10")
        parser.addoption("--remote_project_name",
                            dest="remote_project_name",
                            help="The project name if its run in BrowserStack",
                            default=None)
        parser.addoption("--remote_build_name",
                            dest="remote_build_name",
                            help="The build name if its run in BrowserStack",
                            default=None)
 
    except Exception as e:
        print("Exception when trying to run test: %s"%__file__)
        print("Python says:%s"%str(e))

Get LambdaTest webdriver:

From the above step, we will get details about os, os_version, browser, browser_version on which we need to run the test and what will be the name of the test, the project name and the build name. Now we need to use this information to configure LambdaTest Webdriver correctly.

Create a Python file with the name lambdatest_runner.py and keep the below code in it. You can directly use this script in your automation framework also, we neatly wrote it. The below script sets the webdriver correctly to run the test on the provided os, os_version, browser and browser_version and sets the default capabilities along with provided session test name, project name and build name. And returns the webdriver and session_url where you can see the test video and other details.

Note: This is highly simplified code to make this post illustrative. We do not use this quality of the code at clients.

# Content of lambdatest_runner.py
"""
Get the webdriver for LambdaTest browsers.
"""
import os
import time
import requests
from selenium import webdriver
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.ie.options import Options as IeOptions
from selenium.webdriver.chrome.options import Options as ChromeOptions
 
class LambdaTestRunner():
    """Configure and get the webdriver for the LambdaTest"""
    def __init__(self):
        self.username = os.getenv('REMOTE_USERNAME')
        self.password = os.getenv('REMOTE_ACCESS_KEY')
        lambdatest_url = "http://{}:{}@hub.lambdatest.com/wd/hub"
        self.lambdatest_url = lambdatest_url.format(self.username, self.password)
        self.lambdatest_api_server_url = "https://api.lambdatest.com/automation/api/v1"
        self.session_id = None
        self.session_url = None
 
    @staticmethod
    def firefox(browser_version):
        """Set web browser as firefox."""
        options = FirefoxOptions()
        options.browser_version = browser_version
 
        return options
 
    @staticmethod
    def explorer(browser_version):
        """Set web browser as Explorer."""
        options = IeOptions()
        options.browser_version = browser_version
 
        return options
 
    @staticmethod
    def chrome(browser_version):
        """Set web browser as Chrome."""
        options = ChromeOptions()
        options.browser_version = browser_version
 
        return options
 
    def get_browser(self, browser, browser_version):
        """Select the browser."""
        if browser.lower() == 'ff' or browser.lower() == 'firefox':
            desired_capabilities = self.firefox(browser_version)
        elif browser.lower() == 'ie':
            desired_capabilities = self.explorer(browser_version)
        elif browser.lower() == 'chrome':
            desired_capabilities = self.chrome(browser_version)
        else:
            print(f"\nDriverFactory does not know the browser\t{browser}\n")
            desired_capabilities = None
 
        return desired_capabilities
 
    def lambdatest_credentials(self, lambdatest_options):
        """Set LambdaTest credentials."""
        lambdatest_options['user'] = self.username
        lambdatest_options['accessKey'] = self.password
        return lambdatest_options
 
    def set_lambdatest_capabilities(self,remote_project_name, remote_build_name, testname):
        """Set LambdaTest Capabilities"""
        lambdatest_options = {}
        lambdatest_options = self.lambdatest_credentials(lambdatest_options)
        lambdatest_options["build"] = remote_build_name
        lambdatest_options["project"] = remote_project_name
        lambdatest_options["name"] = testname
        lambdatest_options["video"] = True
        lambdatest_options["visual"] = True
        lambdatest_options["network"] = True
        lambdatest_options["w3c"] = True
        lambdatest_options["console"] = True
        lambdatest_options["plugin"] = "python-pytest"
 
        return lambdatest_options
 
    def get_lambdatest_webdriver(self, os_name, os_version, browser, browser_version,
                                 remote_project_name, remote_build_name, testname):
        """Run the test in LambdaTest when remote flag is 'Y'."""
        options = self.get_browser(browser, browser_version)
 
        if options is None:
            raise ValueError(f"Unsupported browser: {browser}")
 
        # Set LambdaTest platform
        options.platformName = f"{os_name} {os_version}"
 
        lambdatest_options = self.set_lambdatest_capabilities(remote_project_name,remote_build_name,
                                                               testname)
 
        options.set_capability('LT:options', lambdatest_options)
        web_driver = webdriver.Remote(command_executor=self.lambdatest_url, options=options)
 
        # Get the session ID and session URL and print it
        self.session_id = web_driver.session_id
        self.session_url = self.get_session_url_with_retries(self.session_id)
 
        return web_driver,self.session_url
 
    def get_session_url_with_retries(self, session_id, retries=5, delay=2, timeout=30):
        """Fetch the session URL using the LambdaTest API with retries."""
        api_url = f"{self.lambdatest_api_server_url}/sessions/{session_id}"
        time.sleep(2)
        for _ in range(retries):
            response = requests.get(api_url, auth=(self.username, self.password),timeout=timeout)
            if response.status_code == 200:
                session_data = response.json()
                test_id = session_data['data']['test_id']
                session_url = f"https://automation.lambdatest.com/test?testID={test_id}"
 
                return session_url
 
            else:
                print(f"Retrying... Status code: {response.status_code}, Response: {response.text}")
                time.sleep(delay)
        raise Exception(f"Failed to fetch session details after {retries} retries.")

Write a simple test to run on LambdaTest:

In the above sections, we set a few command line parameters which are required to configure the LambdaTest web driver and we have a script to configure the Lambdatest web driver correctly. Now, in this section, we need to write a simple test to run on the LambdaTest.

Look at the below code, we wrote a simple pytest which creates a driver object using lambdatest_runner.py and prints the session URL and other platform details where it is running. We can navigate to this session URL to see the run. Test navigates to Qxf2’s tutorial page and verifies the title.

Note: This is highly simplified code to make this post illustrative. We do not use this quality of the code at clients. Our framework uses the Page Object pattern.

Look at test test_example_form.py below.

#Contents of test_example_form.py
#NOTE: This is highly simplified code to make this post illustrative
#We do not use this quality of the code at clients
#Our framework uses the Page Object pattern
 
from lambdatest_runner import LambdaTestRunner
 
def test_example_form(os_name, os_version, browser, browser_version,
                                 remote_project_name, remote_build_name, testname):
    "Test example form"
 
    #Create an driver object
    runner = LambdaTestRunner()
    driver,session_url = runner.get_lambdatest_webdriver(os_name, os_version, browser, browser_version,
                                        remote_project_name, remote_build_name, testname)
    print("\nRunning test on LambdaTest Platform")
    print("Session url:",session_url)
    #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("Browser: ",browser)
    print("Browser version: ",browser_version)
    print("OS: ",os_name)
    print("OS version: ",os_version)
    print("\nNavigated to Qxf2's Selenium Tutorial page")
    #Check 1: Is the page title correct?
    total_checks += 1 
    if(driver.title=="Qxf2 Services: Selenium training main"):
        print("Success: Title of the Qxf2 Tutorial page is correct")
        pass_check_counter += 1
    else:
        print("Failed: Qxf2 Tutorial page Title is incorrect")
 
    #Quit the browser window
    driver.quit() 
    #Assert if the pass and fail check counters are equal
    assert total_checks == pass_check_counter

Run the test on LambdaTest:

Now we have 3 files conftest.py (to configure test), lambdatest_runner (configure and get LambdaTest webdriver) and test file test_example_form.py. To run test test_example_form we can use the below command:

pytest -s -v --browser firefox --ver 120 --remote_project_name Qxf2_Selenium_Blog_Test --remote_build_name LambdaTest_Blog

Along with the above command, you can also pass the os and os versions with –os_name and –os_version params respectively. By default, it is set to Windows 10.
Look at the test run logs in the below screenshot.

LambdaTest Test Run Logs
Test Run Logs
You can navigate to the provided session URL in logs to watch the test video. Look at the LambdaTest web automation page below.
LambdaTest Web Automation Page
LambdaTest Web Automation Page


Hope this blog helps you to get set with LambdaTest for your automation framework. At Qxf2, we integrated our Page Object Model framework with the LambdaTest. You can refer to our framework readme file for setup and run the test using the below command.

 pytest tests/test_example_forms.py -s -v --remote_flag y

With the correct setup and the above command, test run on the LambdaTest and update test run status also. We will cover how to update the test run status on the LambdaTest web automation page in our upcoming blog.


Hire Qxf2 for your testing needs

Qxf2 is the home of the technical tester. Since 2013, we’ve been early adopters of new testing techniques and tools, staying abreast of technical trends. We offer unique services tailored to small engineering teams building early stage products. You can get in touch with us to learn more about our offerings.


Leave a Reply

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