In this Python unit testing tutorial, learn how to perform unit testing using Python and the unittest framework.
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 built-in, open-source Python testing framework that is easy to use, offering many test assertion methods for easy code validation. All you have to do is import the unittest module into your test script and invoke its TestCase class as an inherited object in your test class.
Here’s an example of how to inherit the unittest TestCase class in your test class while performing unittest testing:
import unittest
class testCaseExample(unittest.TestCase):
def methods(self):
actions…
Deliver immersive digital experiences with Next-Generation Mobile Apps and Cross Browser Testing Cloud
In this Python unit testing tutorial, we will run our test cases on the Windows platform using Python 3.
Install Python and then follow the steps below to set up Python for unit testing:
To create a project folder in VS Code on Windows, follow these steps:
You can run your project globally if you like. However, you want to create a new virtual environment for your test project to avoid dependency interference with the global modules. This isolates your development environment.
Python has a pre-installed virtual environment manager called virtualenv. So you don’t need to install this separately.
To create a virtual environment on Windows,
virtualenv virtual_env_name
cd virtual_env_name/scripts
As mentioned earlier, you don’t need to install unittest separately since it’s a pre-installed Python unit testing framework.
However, you must install Selenium since we’re running a front-end test. You also want to install the dotenv package to retrieve masked sensitive information from your machine’s environment variables. We’ll also add the HTML test runner package, which we’ll use to retrieve and save test results locally.
selenium
python-dotenv
html-testrunner
pip install -r requirements.txt
The project has three main directories:
We’ll use cloud-based grids to run the test cases.
For this, we will use a cloud grid like LambdaTest. It is a reliable and scalable AI-powered test execution platform that empowers you to perform automation testing across real browsers and operating systems.
Moreover, you can also perform Selenium Python testing in parallel, which shortens your overall build times.
Note : Run Your Selenium Tests With Python on the Cloud. Try LambdaTest Now!
The selected platform for our tests is Windows, and we’ll use Firefox as our test browser. You’ll include these details in the test capability, which you can generate from the LambdaTest Automation Capabilities Generator.
setup/setup.py
from selenium import webdriver
from dotenv import load_dotenv
import os
load_dotenv('.env')
LT_USERNAME = os.getenv("grid_username")
LT_ACCESS_KEY = os.getenv("access_key")
desired_caps = {
'LT:Options' : {
"user" : os.getenv("grid_username"),
"accessKey" : os.getenv("access_key"),
"build" : "FireTest New",
"name" : "FireBrowser",
"platformName" : os.getenv("test_OS")
},
"browserName" : "FireFox",
"browserVersion" : "125.0",
}
gridURL = "https://{}:{}@hub.lambdatest.com/wd/hub".format(LT_USERNAME, LT_ACCESS_KEY)
class testSet:
def __init__(self) -> None:
self.driver = webdriver.Remote(command_executor=gridURL, desired_capabilities= desired_caps)
def testSetup(self):
self.driver.implicitly_wait(10)
self.driver.maximize_window()
def tearDown(self):
if (self.driver != None):
print("Cleaning the test environment")
self.driver.quit()
Code Walkthrough:
Start by importing the webdriver module from the Selenium package into the setup script. Then import the os and dotenv packages to extract your grid_username and access_key from your environment variables ( the .env file):
The desired_caps variable is a dictionary of the desired capability specifications for Selenium. This dictionary includes the test name, build name, browser name, and the desired platform’s name. We also declared the gridURL that connects scripts to the LambdaTest cloud servers.
Finally, declare the testSetup() and tearDown() methods. The testSetup() function calls the implicitly_wait() method, which takes a time value (in seconds). This sets the ground for the test, allowing web elements to load before commencing the test steps. The tearDown() function releases the resources used during testing by closing and quitting the browser.
You can learn more about implicit and explicit waits through this blog on Selenium Waits.
Our unit test demonstrations in this Python unit testing tutorial will be black box types (functional unit test) using Selenium; this will assess a few UI functionalities.
If you are new to Selenium, check out our guide on what is Selenium.
Using the HTML runner, we’ll also save the test output in an HTML file. We pass this to the unittest runner inside the event loop while running the test.
Bonus Tip: Besides the HTML runner, you can use the pytest-html module to store your test output as HTML and generate a detailed report. But this requires you to install the pytest and pytest-html modules.
Test Scenario:
|
The next action is to inspect each web page to assess the WebElements. This is where you get insights into the CSS and WebElement selectors.
To inspect an element on a webpage, right-click directly on it and select Inspect. You’ll see the attributes of the selected element, including its class, ID name, or any other relevant selector.
Here’s an inspection of the Form Demo website:
However, since we’re running the tests on the LambdaTest cloud grid, you’ll need to get your access key and username from your LambdaTest Web Automation Dashboard. To do this, navigate to Settings > Account Settings > Password & Security.
Test Implementation:
locators/formLocators.py
from selenium.webdriver.common.by import By
class formLocator:
name = "//input[@id='name']"
email = "//input[@id='inputEmail4']"
password = "//input[@id='inputPassword4']"
company = "//input[@id='company']"
website = "//input[@id='websitename']"
country = "//select[@name='country']"
city = "//input[@id='inputCity']"
address_1 = "//input[@id='inputAddress1']"
address_2 = "//input[@id='inputAddress2']"
state = "inputState"
zip_code = "inputZip"
button = "btn"
locateForm = formLocator()
class formWebAction:
def __init__(self, driver) -> None:
self.driver=driver
def getWeb(self, URL):
self.driver.get(URL)
def getTitle(self):
return self.driver.title
def fillName(self, data):
self.driver.find_element(By.XPATH, locateForm.name).send_keys(data)
def fillEmail(self, data):
self.driver.find_element(By.XPATH, locateForm.email).send_keys(data)
def fillPassword(self, data):
self.driver.find_element(By.XPATH, locateForm.password).send_keys(data)
def fillCompany(self, data):
self.driver.find_element(By.XPATH, locateForm.company).send_keys(data)
def fillWebsite(self, data):
self.driver.find_element(By.XPATH, locateForm.website).send_keys(data)
def fillCountry(self, data):
self.driver.find_element(By.XPATH, locateForm.country).send_keys(data)
def fillCity(self, data):
self.driver.find_element(By.XPATH, locateForm.city).send_keys(data)
def fillAddress1(self, data):
self.driver.find_element(By.XPATH, locateForm.address_1).send_keys(data)
def fillAddress2(self, data):
self.driver.find_element(By.XPATH, locateForm.address_2).send_keys(data)
def fillState(self, data):
self.driver.find_element(By.ID, locateForm.state).send_keys(data)
def fillZipCode(self, data):
self.driver.find_element(By.ID, locateForm.zip_code).send_keys(data)
def submit(self):
self.driver.find_element(By.CLASS_NAME, locateForm.button).click()
Code Walkthrough:
The formLocators.py file contains all the CSS locators and web actions for the form demo website. Separating the selectors this way makes them easy to change as the web elements change. We start by importing the By selector class from the Selenium WebDriver.
Then, we declare a formLocator class to hold all the CSS class names for the web component under test. Besides the state, zip_code, and button attributes, we’ve used the XPath locator format for the other selectors.
XPath locator helps to locate elements faster within the DOM and takes the form:
XPath = //tagname[@Attribute='Value']
For instance, to locate the country field path within the demo form DOM, we used the @name attribute to locate the element from the //select node.
So the XPath selector becomes.
country = "//select[@name = 'country']"
We also instantiate this class to make its attributes callable:
The formWebAction class defines all the web actions for the demo form component based on the driver attribute (declared in the _init_() function). This starts by navigating to the test website and getting its title:
The rest of the methods in the formWebAction class fill each form in the test component, ending with a click on the Submit button. Each form field method accepts a data argument.
testsuites/test_demo_form.py
import unittest
import HtmlTestRunner
import sys
sys.path.append(sys.path[0] + "/..")
from setup.setup import testSet
from locators.formLocators import formWebAction
set_up = testSet()
form = formWebAction(set_up.driver)
class formSampleTest(unittest.TestCase):
def test_unit_user_should_able_to_fill_form(self):
try:
form.getWeb("https://www.lambdatest.com/selenium-playground/input-form-demo")
set_up.testSetup()
title = form.getTitle()
self.assertIn("Selenium", title, "Selenium is not in title")
form.fillName("Idowu")
form.fillEmail("fakeemail@gmail.com")
form.fillPassword("secret")
form.fillCompany("Lambdatest")
form.fillWebsite("someweb.com")
form.fillCountry("Nigeria")
form.fillCity("A City")
form.fillAddress1("Den street")
form.fillAddress2("Den street")
form.fillState("Lagos")
form.fillZipCode("240100")
form.submit()
except AssertionError as e:
print("Something went wrong", e)
set_up.tearDown()
if __name__ == "__main__":
unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='DemoFormHTML_results'))
As you can see, the test_demo_form.py resides in the testsuites directory. So, it executes the web actions accordingly. Import the necessary modules and custom classes. Then, instantiate the testSet() and formWebAction() methods. The formWebAction() method instantiates with the driver attribute from the setup.testSet.
The formSampleTest class inherits the TestCase class from unittest and executes the test steps by calling the actions from the formWebAction instance (form). Note how it starts by navigating to the web page and asserting the title using the assertIn() method.
Navigate to the demo form URL using the getWeb() method. The formWebAction instance runs the actions with the driver attribute from set_up. It then executes the test steps inside the try/except block.
Click the Submit button using the submit() method. The tearDown() method from the setup.testSet class closes used resources and ends the test. We also run the test in an event loop using unittest and HtmlTestRunner.
Test Execution:
Open your command line to the testsuites directory and run the test_demo_form.py file:
python test_demo_form.py
The Python unit test runs on the cloud grid is shown below:
Here are the generated HTML test result:
Here are some best practices for Python unit testing presented in a more conversational tone:
In addition, do subscribe to the LambdaTest YouTube Channel and stay updated with the latest video tutorials on Selenium testing, Selenium Python, and more!
Most successful software products today implement unit testing in their software development pipeline. Failure to perform unit testing while building your app is the first pointer to its potential poor performance. Therefore, it’s better to do it earlier than later.
While system testing is crucial to your user story, unit testing works behind the scenes to improve your existing architecture and user experience. It also makes your code base more maintainable and easy to debug. Finding it hard to trace bug sources in your software?
If you had used Python, you’ve probably ignored Python unit testing earlier in your development cycle. It’s never too late to start testing the pieces into your code base.
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!!