Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Parallel Testing in Selenium WebDriver With Python Using Unittest

DZone 's Guide to

Parallel Testing in Selenium WebDriver With Python Using Unittest

Learn more about parallel testing with Python!

· Performance Zone ·
Free Resource

Cross-browser testing is deemed to be an indispensable task for the modern-day release cycle. However, manual cross-browser testing could turn out to be very strenuous and time-consuming. This is a major hindrance that developers and testers face while performing browser compatibility testing for their website or web application across different operating systems, browsers, etc. This is where Selenium, a free and open source software, steps in!

Selenium is a popular automation testing framework for browser compatibility testing and is utilized for performing automated functional testing with less/minimal learning curve with respect to implementation.

Selenium and Python: Getting Started — Installation, Configuration, and More

Selenium supports the most popular programming languages for testers, namely C#, Java, Ruby, Python, Javascript, PHP, etc., but many developers and testers are opting for Python with Selenium since Python is less verbose than other programming languages. Also, Python libraries are very extensive and help you get more work done by writing clean and better automation code.

Now that you have understood the advantages of using Selenium with Python for automation testing, we explain the basic steps for installation and configuration.

Note: In this blog, we use the Windows Environment, Python version 3.6, and Eclipse as Selenium IDE.

Let's get started:

  1. First, you need to install Python. Choose the appropriate version suitable for your Operating System, i.e. Windows, Linux, Mac, etc.
  2. Ensure that your PATH is appended with the location where Python executable is located. If Python is installed in the location C:\Users\\appdata\local\programs\python\Python36, you need to append the folder location to the environment variable PATH.setpythonpath
  3. Once you have installed Python, the next step is the installation of the Selenium package. It is also termed as ‘Python bindings for Selenium.’ These bindings are critical for performing Python automation testing.pipseleniuminstall
  4. Now, you need to install the most important component in the testing framework — WebDriver. Selenium WebDriver is used for browser automation by pushing commands to the web browser. It is a collection of open-source APIs, and since it is platform-agnostic, source code written for the Windows platform would execute seamlessly on other Operating Systems, e.g. Linux, Mac, etc. This article will highlight how to perform parallel testing in Selenium WebDriver with Python.

Selenium requires the geckodriver in order to communicate with the Firefox browser. For performing parallel testing in Selenium, WebDriver and various browsers can be downloaded from the following locations:

BROWSER DOWNLOAD LOCATION
Firefox https://github.com/mozilla/geckodriver/releases
Google Chrome https://sites.google.com/a/chromium.org/chromedriver/downloads
Microsoft Edge https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/


In the code snippet below, we demonstrate code related to Python automation testing. After importing the Selenium WebDriver library [Lines 3-4], the developer can invoke a Firefox instance by using Option 1 [Line 8], given that the Firefox installation location is updated in the PATH environment variable and geckodriver.exe is executing in the background.

Option 2 [Line 11] can also be used in case you plan to manually invoke geckodriver.exe, which, in turn, starts a Firefox instance.

pythonlibraries

The usage of Selenium Web Server is optional, and it all depends on the manner in which you want to use the Selenium WebDriver. If you are planning to perform parallel testing in Selenium WebDriver with Python, or any other language through your local machine, where you have web browsers on which you intend to use for browser-compatibility testing, WebDriver API would suffice for your requirements. Selenium WebDriver would directly run the browser. Below are the ideal scenarios where you would require the Selenium Web Server:

  • You are performing tests on a browser that is only available in a remote machine, not your local machine.
  • You are using a complex, distributed Selenium Grid for cross-browser testing where the tests are distributed across different Virtual Machines (VMs).
  • You are using HTMLUnit Driver and not Java Bindings, i.e. C#, Ruby, Python, etc.

The Selenium Web Server can be downloaded here.

Selenium WebDriver With Python – Usage and Examples

Now that you have the setup ready, you can now use Selenium WebDriver Python Bindings for the testing of your web application. Below is a simple piece of code that I used for Python automation testing; it will work with the ‘search functionality’ in Google.

Example 1

# Import the necessary modules for development 
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

# Invoke a new Firefox Instance 
ff_driver = webdriver.Firefox()

# Blocking wait of 30 seconds in order to locate the element 
ff_driver.implicitly_wait(30)
ff_driver.maximize_window()

# Open the Home Page
ff_driver.get("http://www.google.com")

# Look for the Search Element and enter the Search Criteria 
search_criteria = ff_driver.find_element_by_id("lst-ib")
search_criteria.clear()

search_criteria.send_keys("Lambda Test")

# Submit the Search results 
search_criteria.submit()

# Sleep for 10 seconds in order to see the results
time.sleep(10)

# Close the Browser instance
ff_driver.close()


You can save the file as search.py and compile using the following command:

python search.py

Note: In case you are using an IDE like Eclipse, you can compile and execute your code using the PLAY button in the Eclipse IDE. Let’s do a code walkthrough and have a look at some of the critical parts in the above example for Selenium Webdriver for Python automation testing.

Import the selenium.webDriver module that provides the WebDriver implementation.

import-selenium-webdriver

Create a Firefox WebDriver instance.

firefoxwebdriver

Open the home page. In any case, the WebDriver will wait until the page loads completely, after which the control returns back to the script. In this example, we have introduced a ‘Blocking Wait’ call of 30 seconds only for demonstration purpose.

implicitytime

The next step is to locate the necessary element on the Web Page. WebDriver offers a number of ways in which find_element_by* can be used to find the required element on the page. In order to find the element name, you can make use of ‘Inspect Element’ functionality in the browser. You need to simply Right+Click on the page and select ‘Inspect Element’ option in order to find the necessary element. Below is the snapshot of finding details about ‘Input Box’ and ‘Google Search’ button on the Google Homepage.

googlesearch

Any pre-populated text in the input box is cleared using the clear() method of the WebDriver, and the Key press is sent using the Keys class imported from selenium.webdriver.common.keys. Once the input operation is complete, submit is invoked using the  submit() method in order to process the Search.

googlesearch
search_criteria

Finally, the browser session is closed using the close() method.

ff_driver.close

Now that you know how Selenium, Python, and WebDriver can be used; we proceed to the next section where we discuss how Selenium can be used for writing effective test cases. In order to write test cases using Selenium, the unittest module has to be imported. Though there are other options like py.test and nose, we will focus on unittest.

Example 2

import unittest
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options

class ChromeSearch(unittest.TestCase):

    def setUp(self):
        chrome_options = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(r"C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe", options=chrome_options)
        self.driver.maximize_window()

    # As per unittest module, individual test should start with test_
    def test_search_lambdatest_chrome(self):
        driver_chrome = self.driver
        driver_chrome.get('http://www.google.com')
        time.sleep(10) 

        search_criteria = driver_chrome.find_element_by_id("lst-ib")
        search_criteria.clear()
        search_criteria.send_keys("Lambda Test")

        # Check if the search returns any result
        assert "No results found." not in driver_chrome.page_source

        search_criteria.submit()
        time.sleep(10)

    def tearDown(self):
        # Close the browser. 
        self.driver.close()

class FirefoxSearch(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.maximize_window()

    # As per unittest module, individual test should start with test_
    def test_search_lambdatest_firefox(self):
        driver_firefox = self.driver
        driver_firefox.get('http://www.google.com')
        time.sleep(10) 

        search_criteria = driver_firefox.find_element_by_id("lst-ib")
        search_criteria.clear()
        search_criteria.send_keys("Lambda Test")

        # Check if the search returns any result
        assert "No results found." not in driver_firefox.page_source

        search_criteria.submit()
        time.sleep(10)


    # Anything declared in tearDown will be executed for all test cases
    def tearDown(self):
        # Close the browser. 
        self.driver.close()

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


The above test code can be executed from the shell using the command  python file-name.py. Let’s do a code walkthrough and focus on the important parts of the code.

Before getting into the actual implementation, important modules are imported. unittest is a built-in Python module that is based on JUnit. It is used for organization of the test cases — more information about unittest can be found here. Similar to the previous example, the selenium.webdriver module, which supports the WebDriver implementation, is imported.

import unittest
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options


Now, we start with the actual testcase implementation. ChromeSearch is the name of the  testcase. The test case class is inherited from unittest.TestCase:

class ChromeSearch(unittest.TestCase):


The setup() method is a part of the initialization and defines instructions that are executed before thetestcase. In the snippet below, we create an instance of Chrome WebDriver for performing Selenium WebdDriver with Python for automation testing.

def setUp(self):
        chrome_options = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(r"C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe", options=chrome_options)
        self.driver.maximize_window()


Once the initialization is done, we proceed with the testcase method. As per the unittest module, individual test should always start with  test_. In the snippet below, the testcase method is  test_search_lambdatest_chrome.  driver_chrome is the local reference to the driver object that was created in the  setUp() method. Henceforth, the local reference (in this case, driver_chrome) will be used for further implementation. For details about the WebDriver implementation, please refer to Example 1 where we have already provided an in-depth explanation.

 def test_search_lambdatest_chrome(self):
        driver_chrome = self.driver


The tearDown() method is called immediately after the test method completes execution, since this is the place where cleanup is performed. In the code snippet below, close operation is performed on the browser, i.e. Chrome.

def tearDown(self):
        # Close the browser. 
        self.driver.close()


The implementation in the  FirefoxSearch testcase method [Line-34] is similar to  ChromeSearch testcase method [Line-7], except that in that method  Firefox WebDriver instance is created.

The final lines of code are the boilerplate code to run the test suite; unittest.main() provides a command-line interface to execute the test script, though there are many other options to execute the tests with a finer level of control.

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


The examples that we have showcased above have a Firefox and Chrome browser at the center of the entire testing process. What if your requirement is to test your web app with just the Firefox browser (version 64.0) installed on a Windows 10 machine? In such a process, you would need the required setup with the same version of Firefox installed on it. This approach is not only expensive but it is also non-scalable.

Conclusion

Performing parallel testing in Selenium WebDriver with Python for automation testing could save you a lot of time by speeding up your slow automated UI tests. If there are less number of tests, you might not require parallel testing in Selenium WebDriver for Python or any other language, but once the complexity of the project increases (or the number of tests to be executed increase), parallel testing is the ideal mechanism to achieve the best results in the minimum possible time. Nowadays, more teams are focused on making use of Continuous Integration (CI) and Continuous Delivery (CD) in the overall software development and testing process. Getting the best out of ‘parallel testing’ is important for the implementation of Continuous Integration (CI).

Happy testing!

Topics:
selenium ,selenium tutorial ,selenium webdriver ,unittest ,parallel testing ,automated testing ,browser compatibility ,performance

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}