Parallel Execution with unittest in Python

Ranvir Chhina
Tauk Blog
Published in
4 min readApr 27, 2022

--

As the size of your codebase grows, developers on your team will continuously add new test cases and build new test suites. If developer changes are deployed using CI/CD, your merges will probably entail running this growing test suite every time to ensure code quality. In my previous blog post, we demonstrated how to write unit test in Python using unittest. To ensure that this growing test suite does not waste developer time, it is necessary to learn how to run these tests in parallel.

Python unittest does not offer a solution to this problem. In this article, I will go over two approaches to running your unittest test cases in parallel. These two approaches are based on two python packages: threading and multiprocessing.

Writing Tests

We will begin by writing a class which extends unittest.TestCase which defines the test fixture for your test cases. In this module, we will override the setUp() and tearDown() methods.

For this particular example, we will be defining a fixture for a selenium test case

  • In the setUp() method, we create an instance of selenium driver for Google Chrome browser. After creating the driver instance, we navigate to Google website.
  • In the tearDown() method, we access the driver which is stored as an instance variable, and exit it using the driver.quit() method.

We will now write the first test case. Create a new class which extends our GoogleTestCase. In this module, we will add the first test.

In this test case, we check if the google home page has a link with text “Gmail” which redirects us to Gmail website when it is clicked.

  • For Tauk setup, we add the observe decorator to make Tauk aware of this test case and then register the driver instance for this test case with Tauk.register_driver()
  • We search for an element with “Gmail” text using the method find_element_by_link_text and store the element reference in the link_with_gmail_text variable.
  • We us the assertIn() method to verify whether the element reference’s href attribute contains the gmail host string.

In a similar fashion, we will create another test case called StoreTest which checks if the google home page has a link with text “Store” which redirects us to Google Store website when it is clicked.

Executing Tests Sequentially

Let us start by creating a module called run.py which runs the above test cases sequentially.

This module imports the test cases that we wrote, packages them into an instance of unittest.TestSuite() and runs them with unittest.TextTestRunner().

There is an additional step you need to do for Tauk setup to work. You need to define the Tauk API Token and Project ID as environment variables. You can do these steps and execute the above module to run tests sequentially using the following command

NOTE: You need to get the API TOKEN and PROJECT ID from the Tauk Web UI. You can learn more about that in this article written by me.

Approach 1: Use Threads for Parallel Execution

The above module creates a class called TestThread which extends threading.Thread. It gets initialized with a test object which is to be run.

  • The Thread objects are passed instances of Test methods which are imported. For example, in t1, GmailTest class is added.
  • The TestThread has overrides the run method of the Thread object.
  • The start() method starts the run() method on a separate child thread.
  • The join() method blocks the main thread and waits for the execution of the test to finish.
  • In the above scenario, we start GmailTest and StoreTest at the same time and then wait for them to end.

This can be started using the same command that is shown in the previous section.

Approach 2: Use Processes for Parallel Execution

It is generally harder to stop threads with meaningful cleanup steps. Instead of having to end your unit tests abruptly, you can use processes which use a different memory space and provide a lot of abstractions when it comes to communications between the primary process and the other processes. It is often harder to debug multithreaded application as well because threads are run atomically and they can only be accessed before or after execution.

You can probably understand most of the code here as it is pretty analogous to threading. Python maintainers have chosen to design threading and multiple processes in a similar fashion.

One additional step, is that Tauk needs to be aware that tests running on separate processes are the same run. You can do so by setting the environment variable TAUK_MULTI_PROCESS before running the tests from the command line in this manner.

Conclusion

In the above sections, we learned how to create a unit test. We learned how to integrate it with Tauk and run these tests sequentially. Next, we added parallel execution and discussed two approaches for it. Hopefully, this short guide will help you save and reduce test execution time for your growing test suite.

Lastly, if you have any questions on this blog post, you can reach out to us by joining our Discord server:

--

--

Tauk Blog
Tauk Blog

Published in Tauk Blog

Enabling developers to efficiently diagnose, resolve, and optimize their automation tests.