Introduction to pytest

pytest is a popular tool for testing Python code. It’s known for being easy to use and having many useful features.

Key Features of pytest

  1. Simple Syntax: You write tests with plain Python functions starting with test_. Use standard assert statements for checks. This makes it easy to start testing.

  2. Rich Assertions: pytest provides clear failure reports. If a test fails, it shows what went wrong with details on variables and expressions.

  3. Fixtures: Fixtures help set up and clean up before and after tests. They let you reuse code for preparing test data or resources.

  4. Parametrization: You can run the same test with different inputs using pytest. This saves you from writing multiple similar tests.

  5. Plugins and Extensions: There are many plugins to add extra features like running tests in parallel, checking code coverage, and more.

  6. Test Discovery: pytest finds and runs tests automatically by looking for files and functions that follow certain naming rules.

These features make pytest a powerful and flexible tool for testing Python code.

Writing Tests with pytest

To get started with pytest, install it using pip:

pip install pytest

Create a test file (e.g., test_sample.py) and write a simple test function:

def test_addition():
    assert 1 + 1 == 2

Run the test using the pytest command:

pytest

pytest will automatically find and run the test, providing a summary of the results.

Advanced Features

  • Fixtures: Define a fixture using the @pytest.fixture decorator to provide setup code for your tests:

      import pytest
    
      @pytest.fixture
      def sample_data():
          return [1, 2, 3]
    
      def test_sum(sample_data):
          assert sum(sample_data) == 6
    
  • Parametrization: Use the @pytest.mark.parametrize decorator to run tests with multiple sets of parameters:

      import pytest
    
      @pytest.mark.parametrize("a, b, expected", [
          (1, 1, 2),
          (2, 3, 5),
          (5, 5, 10)
      ])
      def test_add(a, b, expected):
          assert a + b == expected
    

Unit test example

rearrange.py

#!/usr/bin/env python3

import re

def rearrange_name(full_name):
    match = re.search(r"^([\w .]*), ([\w .]*)$", full_name)
    return "{} {}".format(match[2], match[1])

rearrange_test.py

#!/usr/bin/env python3

import unittest
from rearrange import rearrange_name

class TestRearrange(unittest.TestCase):
    
    def test_rearrange(self):
        input_name = "Lovelace, Ada"
        expected_output = "Ada Lovelace"
        self.assertEqual(rearrange_name(input_name), expected_output)

# Run the tests
unittest.main()

Running the Test

chmod +x rearrange_test.py
./rearrange_test.py

Unittest vs. Pytest

  • Unittest is built into Python and uses an object-oriented approach with special assert methods.
  • Pytest needs to be imported and uses a functional approach with simple assert statements.
  • Unittest automatically detects tests but needs to be run from the command line. Pytest runs tests automatically with the test_ prefix.
  • Both can work together; you can use pytest with unittest code.

Choose based on your preference: unittest for built-in simplicity or pytest for easier, more readable tests.

Conclusion

pytest is a handy tool for testing Python code. It’s easy to use, has many features, and is well-supported by the community. Ideal for both small and big projects, it helps you write reliable tests quickly.

Some important concepts regarding testing

  1. Black-box test:
    • This is a type of testing where the tester doesn’t look at the internal code of the software. They just check if the software works as expected based on inputs and outputs.
  2. Integration test:
    • This test checks if different parts of the software work well together. It ensures that the combined parts function correctly with each other and with external systems.
  3. Isolation:
    • In testing, isolation means ensuring that a test only checks one specific part of the software. Any success or failure should be due to the part being tested, not because of something else.
  4. Regression test:
    • This is a test done after fixing a bug to make sure that the bug doesn’t come back. It checks if the new changes have affected the existing functionality.
  5. Load test:
    • This type of testing checks how well the software performs under heavy use. It ensures that the software can handle a large number of users or high data loads without crashing.
  6. Smoke test:
    • This is a basic test to check if the main functions of the software are working. It’s like a quick check to see if the software is stable enough for more detailed testing.
  7. White-box test:
    • This is a type of testing where the tester looks at the internal code and structure of the software. They check if the internal workings are correct and efficient.
  8. Test-driven development:
    • This is a software development process where tests are written before the actual code. Developers first write a test for a small part of the functionality, then write the code to pass that test, and finally, improve the code while keeping the test passing.