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:
- Simplicity: Pytest is easy to learn. You write test functions with simple
assert
statements, and it handles the rest. - Automatic Discovery: Pytest automatically finds tests by looking for filenames starting with
test_
or ending in_test.py
. - 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:
TECKNET Wireless Mouse, 2.4G Ergonomic Optical Mouse, Computer Mouse for Laptop, PC, Computer, Chromebook, Notebook, 6 Buttons, 24 Months Battery Life, 2600 DPI, 5 Adjustment Levels
$8.49 (as of January 9, 2025 10:16 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)The Nvidia Way: Jensen Huang and the Making of a Tech Giant
$26.16 (as of January 11, 2025 10:31 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Anker USB C to USB C Cable (6FT, 2Pack), Type C 100W Charger Cord Fast Charging for iPhone 16 Series,MacBook Pro 2020,Pixel And More(USB 2.0,Black)
$8.99 (as of January 9, 2025 10:16 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)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
.
# 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:
# 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
orsubtract
). - 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:
========================== 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:
- Import Errors:
Ifpytest
can’t find theCalculator
class, make sure your project structure has__init__.py
files in all relevant folders. Also, runpytest
from the root of the project, not inside thetests
directory. - Missing Pytest:
If you see an error likeModuleNotFoundError: No module named 'pytest'
, install it using pip:
pip install pytest
- Python Path Issues:
If the import still fails, you can temporarily set thePYTHONPATH
to the project root when runningpytest
:
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!