Test automation in Python. Six Ways to Test Effectively

We have already talked about test automation, now it’s time to get to know the six best test automation tools in Python.

The good news is that the Python standard library already has some great unit testing tools. You can build robust test automation with built-in language capabilities for a very long time. But adding automation to the standard Python codebase is easy because the language is used for a variety of tasks, including building the test automation tools themselves.

You can customize the degree and level of test automation you want in Python, and create tests to suit your growing code base.

So, let’s begin.

PyUnit and Nose2

PyUnit Is a Python unit testing framework. It was added to the Python standard library back in version 2.1 and is compatible with all subsequent versions of the language. PyUnit is a Python implementation of JUnit, the standard Java unit testing framework. This is why developers who switch from Java to Python will find it very easy to use. Both frameworks owe their existence to the Smalltalk Testing Framework by Kent Beck.

PyUnit contains all the tools you need to create automated tests.

  • Fixtures with which you can create and delete objects required for the test.

  • Methods for executing tests.

  • Sets for grouping test classes into logical units.

  • Runners for performing tests.

Here’s an example of a basic unit test:

import unittest
    class SimpleWidgetTestCase(unittest.TestCase):
        def setUp(self):
            self.widget = Widget("The widget")
    class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
        def runTest(self):
            assert self.widget.size() == (50,50), 'incorrect default size'

SimpleWidgetTestCase uses fixture setUp, to create Widget for testing. DefaultWidgetSizeTestCase Is the inheritor class SimpleWidgetTestCasewhich checks the size Widget

PyUnit is a great place to start setting up test automation in Python, but it’s just a basic set of tools. You will also need tools to automate test execution and collect results. This is where Nose

Nose2 Is the next step after PyUnit. It adds support for automatic test detection and plugins to run tests and generate documentation. The Nose2 plugin system adds additional functionality in the form of decorators, parameterized tests, and test search. For example, AllModules finds all tests and gathers output from them.

Nose2 also contains Such – DSL for writing functional tests.

If you put the code in a file named test_widgets.py, the Nose2 test runner will find the test and run it. All you have to do is add a prefix to your files. tests_


PyTest (https://pytest.org/en/latest/) Is a native Python testing library, it contains an extended set of PyUnit functions. Compared to modeling the JUnit architecture, it is definitely written in Python style. She makes extensive use of Python decorators and assertions.

PyTest also supports parameterized testing (no Nose plugins), which makes code reuse and test coverage easier.

If you rewrite the test we wrote above for Pytest, it will look more declarative.

def widget():
    return Widget("The widget")
def test_widget_size(widget):
    assert widget.size() == (50,50), 'incorrect default size'

PyTest uses test fixtures to pass the Widget to the test method.

In addition to fixtures, test suites, and test runners, PyTest has its own support for finding tests. You can choose which test suites to run based on the names of methods, packages, or decorators that you add to your test code. PyTest also knows how to run tests in parallel. By using these functions at the same time, you make it easier for yourself to manage large codebases compared to PyUnit.

PyTest makes it easy to create reports in plain text, XML, or Html… Also you can add information about code coverage into PyTest reports.

While PyTest can be used on its own, you can integrate it with other testing frameworks and test runners such as PyUnit and Nose2. This compatibility makes PyTest an excellent choice for growing projects that need good test coverage. PyTest requires Python 3.6 or later.


PyUnit and PyTest are powerful traditional unit testing frameworks, but what if you want behavior-driven tests?

Behave Is a behavior-driven (BDD) testing framework. It is critically different from PyUnit and PyTest. In it you write tests for Gherkin instead of Python. Although not Cucumber’s original Gherkin here, Behave has full Gherkin support, making it one of the most popular BDD frameworks for Python.

Behave is so ubiquitous that even Jetbrains has a plugin for it in PyCharm Professional Edition… There are also many online tutorials and documentation for working with Behave.

You describe tests in natural language grammar, and you describe a function in terms of behavior and expected test results. Then you write your tests with annotations that match the behavior and conditions. Behave runs tests, collects results, and documents them as behavior files.

If you are interested in or even already using behavior-driven development (BDD), Behave is one of the best options for this. It comes with integrations for both Django and Flask, so you can use it in full-stack projects.

The test from the previous examples can be implemented on Behave as shown below.

Here is the natural language grammar:

Feature: widget size
  Scenario: verify a widget's size
     Given we have a widget
     When the widget is valid
     Then the size is correct

And here is the Python code. Have Given, When and Then there are corresponding annotations.

from behave import *

@given('we have a widget')
def step_given_a_widget(context):
    context.widget = Widget('The widget')   

@when('the widget is valid')
def step_widget_is_valid(context)
    assert context.widget is not None

@then('the size is correct')
def step_impl(context):
    assert context.widget.size() == (50,50)


Lettuce Is a behavior-driven automation tool for Selenium and Python. Like Behave, it uses Gherkin syntax to describe test scripts, but it does not have the same compatibility as Behave. Lettuce is not as common as Behave, however it works well for small projects.

It’s also easy to integrate with other frameworks like Selenium and Nose

Lettuce tests are somewhat similar to Behave tests. This is how it looks in natural language:

Feature: widget size 

Scenario: verify a widget's size 
    Given we have a widget 
    When the widget is valid 
    Then the size is correct

And here’s the code. Instead of a separate annotation for each test step, Lettuce annotates itself step

from lettuce import step
from lettuce import world 

@step('we have a widget') 
def step_given_a_widget(step):
    world.widget = Widget('The widget') 

@step('the widget is valid')
def step_widget_is_valid(step) 
    assert world.widget is not None 

@step('the size is corrrect') 
def step_impl(context): 
    assert world.widget.size() == (50,50)

When you integrate Lettuce with Selenium, you have a robust framework for testing Django applications. So if you don’t like Jasmine’s JavaScript syntax, this might be the best option.

However, Lettuce hasn’t been updated since 2016. You can still download it and use it in your code, but it is no longer supported.

Jasmine for Python test automation

BDD is not just a popular Python development paradigm, it is also widespread in web development. Jasmine Is a popular BDD style web application testing framework. Most likely you think of Jasmine as a JavaScript application testing tool, but you can use it to automate testing in Python.

Thanks to Jasmine-Py you can add Jasmine to your Django projects. This will allow you to run Jasmine from your Python environment and from your CI / CD server.

Testing web applications based on behavior rather than DOM makes your tests more resilient to change. This becomes a huge benefit the moment you test how Django code creates pages. Instead of Gherkin, you will write tests in Jasmine grammar

The results can be applied to both your website and your Django code.

Robot framework

Robot framework Is an open source test automation framework. Organizations use it to automate acceptance testing. You write tests in the Robot DSL, the syntax used to create acceptance tests.

Instead of focusing on behavior like in Jasmine, Robot focuses on keywords.

A keyword is any function or method that you can call in your test. Keywords are defined either in Robot, the main system, or custom libraries for testing. You can also define new keywords in terms of existing keywords.

You can extend Robot’s capabilities with testing libraries written in Python or Java. So, in addition to using this framework to test your Python code, you can extend Robot with Python. You also have access to extensive library plugins for Robot.

The DSL framework makes it easy to create scripts for test automation. With the right set of plugins, you can automate almost every aspect of acceptance testing. You can also create new higher-level keywords using existing ones.

You definitely need Python test automation

Python has grown steadily in popularity over the past decade. You can see her height in TIOBE index… Chances are good that you are already writing in Python or planning to add it to your toolkit soon.

The expanding scope of Python has led to the proliferation of frameworks, testing tools, and other utilities. Whether you are creating a backend REST service or any other application, there is a suitable automated testing framework for you.

Which one will best suit your needs? Testim has a guide to help you make an informed decision. Refer to him and start testing in Python today.

Translation prepared as part of the course “Python QA Engineer”… We invite everyone to an online open day: at this meeting you will learn more about the course program and the training format, get to know the teacher. Register here

Similar Posts

Leave a Reply

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