In this tutorial, learn how to run Python unit tests using the unittest framework, along with real-world examples.
OVERVIEW
Unit testing is a method where individual units or components of a software application are tested independently to ensure they function as intended. When it comes to automated testing, you can use various programming languages, such as Python, to help automate unit testing.
Typically, Python unit testing involves leveraging frameworks such as unittest, which lets you write unit test cases to validate each unit of software applications.
Python lets developers and testers perform unit testing, offering a range of built-in libraries and frameworks like unittest, doctest, and more. These frameworks for Python automation testing simplify the creation and execution of unit tests with advanced features and functionalities, enhancing the testing workflow.
Among these, the unittest module—a core part of Python's standard library—is a complete framework for setting up and executing unit tests. It features test discovery, fixtures, suites, and various assertion methods to evaluate the expected versus actual results.
unittest is a Python-based framework inspired by the JUnit framework. It provides a framework for writing and running automated tests.
Some of its key features include:
Since the unittest framework comes pre-installed with Python, you'll need to install Python if you haven't already. Download the latest version of Python from the official Python website. After downloading, run the installer and follow the on-screen instructions.
To verify the installation, open your terminal and type:
python --version
To verify if unittest is available, create a .py file and run the following line of code:
import unittest
Once all installations are verified, we can write our test cases.
To achieve better scalability and reliability, we will run our tests on the cloud. For this, we will use cloud-based testing platforms such as LambdaTest. It is a reliable and scalable AI-powered test execution platform that empowers you to perform the unittest testing using Python across real browsers and operating systems.
Note : Run Selenium tests with Python on the cloud. Try LambdaTest Now!
You can get your LambdaTest Username and Access Key from your LambdaTest Account Settings > Password & Security. It is also required to install the python-dotenv package in order to read the .env file. Paste your LambdaTest credentials in the .env file as shown below:
LT_USERNAME= <username>
LT_ACCESS_KEY= <access_key>
In the following code snippet, we'll define the options related to Chrome, which will serve as metadata in a JSON format, as shown below:
//lt_options.json
{
"build": "Build: Python Unittest Demo",
"project": "Project: Python Unittest Demo",
"name": "Test: Python Unittest Demo",
"w3c": true,
"selenium_version": "latest",
"plugin": "python-python",
"platform": "Windows 11",
"browserName": "Chrome",
"version": "latest",
"visual": false,
"network": true,
"console": true,
"video": true
}
The JSON file defines configuration parameters for our testing environment in Chrome, such as the Selenium version to use and the platform to test on. The LambdaTest Automation Capabilities Generator can be used to generate the appropriate configurations for the test environment.
We'll load the provided JSON and pass it to ChromeOptions. Then, we'll execute a remote WebDriver instance to run Selenium tests on the LambdaTest platform, utilizing the credentials. You can find the code snippet in the pyunitsetup.py file.
self.driver = webdriver.Remote(
command_executor=f"https://{lt_username}:{lt_access_key}@hub.lambdatest.com/wd/hub",
options=chrome_options
)
# self.driver = webdriver.Chrome()
Each test initializes the PyUnitTestSetup class, which includes instantiating a driver and passing the lt_options to configure remote test execution. This setup is particularly useful for cross browser testing and can be configured to work with cloud testing platforms like LambdaTest.
Let’s use the LambdaTest eCommerce Playground to test different test scenarios to check different functionalities such as login, card badge update, add to cart, continue shopping, and logout.
You can find the test script for these test cases in the unittest_with_selenium.py file.
It follows the same process as the cart badge update test by selecting and adding the item to the cart. After adding the item to the cart, we review the cart and validate the name of the item added to the cart with what was actually added.
After adding the element to the cart, we go to the cart, press the Continue Shopping button, and validate if we are on the home page. We use the ActionChains object that allows you to create chains of actions (like mouse movements, clicks, etc.) and then execute them as a single action. It's useful for performing complex interactions that involve mouse movements or keyboard actions.
First, we'll log in using the previous credentials with the existing login function logic. After this, we will log out of the account.
Deliver immersive digital experiences with Next-Generation Mobile Apps and Cross Browser Testing Cloud
Now, we will run our Python unit tests both sequentially and in parallel.
Before we run the tests sequentially, we will need to wrap our previous functions in a class inherited from TestCase. We can wrap all the functions in a single class, but since we also need to show parallel execution, we will create two classes.
class TestLoginPage(unittest.TestCase):
def test_login(self):
… … … …
def test_logout(self):
… … … …
Similarly, we can create for the other three functions:
class TestPlatform(unittest.TestCase):
def test_cart_badge_update(self):
… … … …
def test_add_to_cart_functionality(self):
… … … …
def test_continue_shopping(self):
… … … …
Now that we have the test case defined wrapped in a class inherited with the TestCase class, we can execute test cases from the terminal.
Run the following command to execute the test:
python -m unittest unittest_with_selenium.py
Output:
To run the test cases in parallel, we will use a multiprocessing package in Python. We will create separate threads for our two test case suites and run them independently. A fair note using this approach is to make sure that the test cases are independent of each other.
import unittest
import multiprocessing
# Import your test classes here
from unittest_with_selenium import TestLoginPage,TestPlatform
# List of test classes to run
test_classes = [TestLoginPage, TestPlatform]
def run_tests(test_class):
suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
unittest.TextTestRunner().run(suite)
if __name__ == '__main__':
processes = []
# for test_class in [MyTest, MyTest2]: # Add more test classes here if needed
for test_class in test_classes: # Add more test classes here if needed
process = multiprocessing.Process(target=run_tests, args=(test_class,))
processes.append(process)
process.start()
for process in processes:
process.join()
After running the scripts from above, the tests will also be logged on to the LambdaTest Web Automation dashboard as seen below:
As we can see, all 5 tests are executed and are shown on the dashboard. This is what is displayed on the terminal for a sequential run.
You can further deep dive into the tests and see the events executed.
Now that we understand how unit testing is performed in Python, here are a few key best practices to follow for optimized results. With these best practices, you can make your unit tests using the unittest framework in Python more efficient, readable, and maintainable.
import unittest
def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(YourTestClass))
return suite
class MyTest(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def tearDown(self):
self.driver.quit()
def test_example(self):
self.driver.get("https://www.example.com")
if __name__ == "__main__":
unittest.main()
self.assertEqual(a, b)
self.assertTrue(x)
self.assertFalse(x)
self.assertRaises(Exception, func, *args, **kwargs)
python -m unittest discover
from unittest.mock import MagicMock
mock = MagicMock(return_value=10)
mock.method()
In the below example, the @parameterized.expand decorator runs the test_parameterized method with different sets of parameters. Each tuple in the list represents an input `i` and expected output, allowing you to test the i % 2 operation with various values and verify the results.
import unittest
from parameterized import parameterized
class MyTest(unittest.TestCase):
@parameterized.expand([
(0, 0),
(1, 1),
(2, 0),
(3, 1),
(4, 0),
])
def test_parameterized(self, i, expected):
self.assertEqual(i % 2, expected)
if __name__ == "__main__":
unittest.main()
loader = unittest.TestLoader()
tests = loader.loadTestsFromTestCase(MyTest)
testRunner = unittest.TextTestRunner()
testRunner.run(tests)
In addition, subscribe to the LambdaTest YouTube Channel and stay updated with the latest video tutorials on Python automation testing, Selenium Python, and more!
Unit testing is one of the key testing practices that developers follow to ensure a robust codebase. It allows developers to test their code granularly and ensure that all modules (units) behave as expected.
Python provides a native unittest framework that comes natively installed with the language. This framework can be used to write and execute Python unit tests with a single command. The framework provides various functionalities, such as built-in logical assertions, executing all tests with a single command, and functions for resource initialization and deallocation.
Streamline test authoring, management, execution, and reporting to boost efficiency throughout all testing phases.
Did you find this page helpful?
Try LambdaTest Now !!
Get 100 minutes of automation test minutes FREE!!