Setting Up Python Project Testing with Pytest

Testing is one of those steps in software development that separates a hobby project from a professional one. Whether you’re building something small or maintaining a complex codebase, testing ensures your code does what it’s supposed to do. If you’re new to testing in Python, pytest is one of the easiest tools to get started with. In this post, I’ll walk you through setting up pytest for a Python project and writing your very first test for a class. I’ll also cover how to handle common pitfalls, like dealing with folder structures and import issues.

Thank me by sharing on Twitter 🙏

By the end of this tutorial, you’ll have a working test suite, a better understanding of Python project organization, and confidence to write your own tests moving forward.

Why Use Pytest for Testing in Python?

There are plenty of testing tools out there, so why use pytest? For me, it comes down to three things:

  1. Simplicity: Pytest is easy to learn. You write test functions with simple assert statements, and it handles the rest.
  2. Automatic Discovery: Pytest automatically finds tests by looking for filenames starting with test_ or ending in _test.py.
  3. Powerful Features: Even though it’s simple, it’s powerful. You can use fixtures, parametrized tests, and plugins as your needs grow.

If you’re setting up testing for the first time, pytest is the ideal tool to start with.

Setting Up the Project Structure

Let’s start with a basic Python project. A clean folder structure makes it easier to organize code and tests. Here’s an example of how your project might look:

Plaintext
my_project/
├── classes
│   ├── __init__.py
│   └── calculator.py
├── tests
│   ├── __init__.py
│   └── classes
│       ├── __init__.py
│       └── test_calculator.py

Here’s what these folders mean:

  • classes/: This folder contains your main application code. For example, calculator.py is where your class will be defined.
  • tests/: This is where all test files live. Each file tests a specific module or set of functions.
  • __init__.py: These files make the folders Python packages. They can be empty, but they help with imports.

This structure keeps your tests separate from your code while mirroring the organization of your application.

Writing the Class to Test

Before we write the test, let’s create a simple class in classes/calculator.py. I’m using a Calculator class with two methods: add and subtract.

Python
# classes/calculator.py

class Calculator:
    def add(self, a, b):
        return a + b

    def subtract(self, a, b):
        return a - b

This is the class we’re going to test. It’s straightforward, but it’s enough to demonstrate the basics of testing with pytest.

Setting Up the Test File

Now, let’s move to tests/classes/test_calculator.py. This file will contain all the tests for the Calculator class.

Before you write tests, you need to import the class you want to test. Here’s where things can get tricky if you’re unfamiliar with Python imports.

To import the Calculator class from classes/calculator.py, use the following line:

from classes.calculator import Calculator

Now, let’s write some tests.

Writing the First Tests with Pytest

With the class imported, we can write a few basic tests. In pytest, a test function must start with the word test_ so that pytest can discover it automatically.

Here’s an example of two tests:

Python
# tests/classes/test_calculator.py

from classes.calculator import Calculator

def test_add():
    calc = Calculator()
    result = calc.add(2, 3)
    assert result == 5  # Test passes if result equals 5

def test_subtract():
    calc = Calculator()
    result = calc.subtract(10, 5)
    assert result == 5  # Test passes if result equals 5

In these tests:

  • We create an instance of the Calculator class.
  • We call the method we want to test (add or subtract).
  • We use assert to check that the result is what we expect.

If the assertion fails, pytest will tell you exactly what went wrong.

Running the Tests

To run the tests, open a terminal and navigate to the root of your project (the folder containing the classes and tests directories). Then, run this command:

pytest

Pytest will automatically look for test files, execute the test functions, and show you the results.

A successful test run will look something like this:

Plaintext
========================== test session starts ===========================
collected 2 items

tests/classes/test_calculator.py ..                                     [100%]

=========================== 2 passed in 0.01s ============================

If a test fails, you’ll see an error message showing which assertion failed and what the actual result was. This makes debugging straightforward.

Common Issues and Fixes

When setting up pytest for the first time, you might encounter a few issues. Here’s how to solve the most common ones:

  1. Import Errors:
    If pytest can’t find the Calculator class, make sure your project structure has __init__.py files in all relevant folders. Also, run pytest from the root of the project, not inside the tests directory.
  2. Missing Pytest:
    If you see an error like ModuleNotFoundError: No module named 'pytest', install it using pip:
   pip install pytest
  1. Python Path Issues:
    If the import still fails, you can temporarily set the PYTHONPATH to the project root when running pytest:
   PYTHONPATH=. pytest

These steps should resolve most of the common problems you might face.

What Comes Next?

Once you have the basics of pytest down, there’s a lot more you can explore. For example:

  • Fixtures: Use fixtures to set up reusable test data.
  • Parametrized Tests: Test multiple inputs and expected results with a single function.
  • Plugins: Extend pytest with plugins for coverage reports, mocking, and more.

Testing doesn’t have to be an afterthought. Even simple tests like the ones we wrote here can help you catch bugs early and save hours of debugging later.

Conclusion

Setting up pytest for the first time can feel intimidating, but it doesn’t have to be. By organizing your project, writing simple test functions, and running them with pytest, you can build confidence in your code and catch errors early.

In this guide, we created a basic project structure, wrote a Calculator class, and tested it with pytest. From here, you can expand your tests to cover edge cases, handle more complex logic, and make testing an integral part of your development workflow.

With a solid foundation, you’re now ready to start testing your own Python projects. Give it a try, and you’ll see how much easier it makes your life as a developer!

Share this:

Leave a Reply