Logo

Testing

Learning Outcomes

  • What is unit testing
  • How to unit test with the unittest and pytest modules
  • How to use fixtures to set up and tear down tests
  • How to assert statements in tests

About this Lesson

Being able to test our programs is an important skill to have to ensure that your code is working as expected. We will first go over the built-in unittest module and then proceed with the similar but more powerful pytest module.


Writing Tests with unittest

Tests in the unittest module are written as functions within a class that inherits from the unittest.TestCase class. We can use the `assertEqual`` method to check if two values are equal. If the condition is false, the test fails, and if it's true, the test passes.

import unittest

class TestAddition(unittest.TestCase):
  def test_add_integers(self):
    self.assertEqual(1 + 1, 2)
  def test_add_strings(self):
    self.assertEqual('foo' + 'bar', 'foobar')

We can also use the following common assert methods:

  • assertNotEqual, which is the opposite of assertEqual
  • assertTrue and assertFalse
  • assertIsNone and assertIsNotNone
  • assertIn and assertNotIn
  • assertRaises

Running Tests with unittest

To run our tests, we can use the following command:

python -m unittest test_addition.py

where test_addition.py is the name of the file containing our tests. If any of the tests fail, the output will show the line number and name of the failed test along with the error message.


Test Fixtures

We can use test fixtures to set up and remove an environment for our tests. The setUp method is used to run instructions before each test, and the tearDown method is run after each test. Let's say we want to test with the contents of a file, we would want to have an isolated environment where we create the file with our contents before each test and remove it after each test.

import unittest
import os

class Test_Files(unittest.TestCase):
    def setUp(self):
        self.file = open("data.txt", "w")
        self.file.write("Entry 1\nEntry 2")
        self.file.close()
    def tearDown(self):
        os.remove("data.txt")
    def test_file_contents(self):
        self.file = open("data.txt", "r")
        contents = self.file.read()
        self.assertEqual(contents, "Entry 1\nEntry 2")
        self.file.close()

Testing with pytest

Pytest is a simpler yet more powerful testing framework as opposed to the built-in unittest module. To get started, we will need to install pytest with the following command:

pip install pytest

Writing tests is similar to the unittest module, but we can create functions in our code that start with test_ and pytest will automatically run them. Instead of using assert functions, we use the assert keyword and write our expression after it.

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

And to run our tests, we can use the following command:

pytest test_addition.py

where test_addition.py is the name of the file containing our tests. We can still group our tests into a class, but we will need to also prefix the class name with Test.

class Test_Addition:
    def test_add_integers(self):
        assert 1 + 1 == 2
    def test_add_strings(self):
        assert 'foo' + 'bar' == 'foobar'

Fixtures in pytest are similar to the unittest module, but we use the @pytest.fixture decorator instead of the setUp and tearDown methods. We use the yield keyword to yield our setup (in this case the path to our file path). If no tear down procedure is needed, use the return keyword for your setup instead of the yield keyword.

import pytest

@pytest.fixture
def data_file(tmp_path):
    file_path = tmp_path / "data.txt"
    with open(file_path, "w") as f:
        f.write("Entry 1\nEntry 2")
    yield file_path
    file_path.unlink()

def test_file_contents(data_file):
    with open(data_file, "r") as f:
        contents = f.read()
    assert contents == "Entry 1\nEntry 2"

pytest has a lot more features such as support for mocking and plugins for testing web applications and databases. You can read more about it here.

Knowledge Check

  • What is unit testing?
  • How do the unittest and pytest modules differ?
  • How do we assert statements in unittest? How about in pytest?
  • What is a test fixture?
  • Why are the setUp and tearDown methods useful?

Additional Resources

Contribute to this lesson