Pytest is a Python testing framework that originated from the PyPy project. It can be used to write various types of software tests, including unit tests, integration tests, end-to-end tests, and functional tests. Its features include parametrized testing, fixtures, and assert re-writing.

Pytest fixtures provide the contexts for tests by passing in parameter names in test cases; its parametrization eliminates duplicate code for testing multiple sets of input and output; and its rewritten assert statements provide detailed output for causes of failures.

Pytest

History

Pytest was developed as part of an effort by third-party packages to address Python's built-in module unittest's shortcomings. It originated as part of PyPy, an alternative implementation of Python to the standard CPython. Since its creation in early 2003, PyPy has had a heavy emphasis on testing. PyPy had unit tests for newly written code, regression tests for bugs, and integration tests using CPython's test suite.

Pytest

In mid 2004, a testing framework called utest emerged and contributors to PyPy began converting existing test cases to utest. Meanwhile, at EuroPython 2004 a complementary standard library for testing, named std, was invented. This package laid out the principles, such as assert rewriting, of what would later become pytest. In late 2004, the std project was renamed to py, std.utest became py.test, and the py library was separated from PyPy. In November 2010, pytest 2.0.0 was released as a package separate from py. It was still called py.test until August 2016, but following the release of pytest 3.0.0 the recommended command line entry point became pytest.

Pytest

Pytest has been classified by developer security platform Snyk as one of the key ecosystem projects in Python due to its popularity. Some well-known projects who switched to pytest from unittest and nose (another testing package) include those of Mozilla and Dropbox.

Features

Parametrized testing

It is a common pattern in software testing to send values through test functions and check for correct output. In many cases, in order to thoroughly test functionalities, one needs to test multiple sets of input/output, and writing such cases separately would cause duplicate code as most of the actions would remain the same, only differing in input/output values. Pytest's parametrized testing feature eliminates such duplicate code by combining different iterations into one test case, then running these iterations and displaying each test's result separately.

Parametrized tests in pytest are marked by the decorator, where the first parameter, , is a string of comma-separated names, and is a list of values to pass into . When there are multiple names in , would be a list of tuples where values in each tuple corresponds to the names in by index. The names in are then passed into the test function marked by the decorator as parameters. When pytest runs such decorated tests, each pair of and would constitute a separate run with its own test output and unique identifier. The identifier can then be used to run individual data pairs.

Assert rewriting

When writing software tests, the assert statement is a primary means for communicating test failure, where expected values are compared to actual values. While Python's built-in assert keyword would only raise AssertionError with no details in cases of failure, pytest rewrites Python's assert keyword and provides detailed output for the causes of failures, such as what expressions in the assert statement evaluate to. A comparison can be made with unittest (Python's built-in module for testing)'s assert statements:

adheres to a more verbose syntax because it is inspired by the Java programming language's JUnit, as are most unit testing libraries; pytest achieves the same while intercepting Python's built-in assert calls, making the approach more concise.