Manual testing works well when a Python program is small. You run the file, enter a few values, and check the result yourself. As the project grows, however, repeating the same checks after every change becomes slow and easy to forget. This is where Pytest in Python becomes especially useful.
Pytest lets you write small automated tests that confirm whether your functions still behave as expected. When something breaks, it reports which test failed, where the failure happened, and which values were compared.
In this beginner-friendly guide, you will learn how to install Pytest, write your first test, understand assert, test expected exceptions, organize test files, and use the most helpful commands. No previous experience with automated testing is required.
What Is Pytest?
Pytest is a testing framework for Python. It discovers and runs test functions, then gives you a clear report showing which tests passed and which ones failed.
An automated test is simply code that runs another part of your program and compares the actual result with the expected result. Suppose you have a function that adds two numbers. You expect add(2, 3) to return 5. Instead of checking that manually after every change, you can write a test that performs the verification in milliseconds.
Pytest is commonly used for unit testing in Python. A unit test usually checks a small piece of a program, such as one function or method. Pytest can also support larger test suites for APIs, databases, command-line tools, and web applications.
One reason beginners like Pytest is its simple syntax. In many cases, you only need a function whose name starts with test_ and an assert statement. You can begin with the basics and add more advanced features later.
Why Should You Learn Pytest?
Automated tests are not limited to large companies or complex software. They are also valuable in personal projects, coding exercises, data scripts, and small automation tools.
Tests help you change code with more confidence. After editing a function, you can run the entire test suite and quickly see whether an existing behavior was accidentally broken.
- Catch mistakes soon after a code change.
- Prevent previously fixed bugs from returning.
- Document how a function is expected to behave.
- Make refactoring safer.
- Reduce repetitive manual checks.
- Improve confidence before releasing a new version.
A passing test suite does not prove that an application has no bugs. It only confirms the behaviors covered by the tests you wrote. Good tests therefore focus on meaningful cases, including normal inputs, edge cases, and invalid values.
What You Need Before Starting
To follow this tutorial, you need Python installed and basic familiarity with running commands in a terminal. It also helps to understand how functions work. If that topic is still new, review this introduction to Python functions.
You can write the examples in any code editor. Visual Studio Code is a practical choice, but the same files will work in PyCharm, IDLE, or another editor.
Create a folder named pytest_project and open it in your editor. Using a virtual environment is strongly recommended because it keeps the project’s dependencies separate from packages installed elsewhere on your computer. This guide to creating a Python virtual environment with venv explains the process in more detail.
How to Install Pytest
Open a terminal inside your project folder and create a virtual environment:
python -m venv .venvOn Windows, activate it with:
.venv\Scripts\activateOn Linux or macOS, use:
source .venv/bin/activateNow install Pytest:
python -m pip install -U pytestYou will often see pip install pytest in tutorials. Using python -m pip helps ensure that the package is installed for the same Python interpreter used by the project. For more background, see how to install Python packages with pip.
Confirm that the installation worked:
pytest --versionThe terminal should display the installed version. The official Pytest getting-started guide uses the same installation and version-checking process. The Python Packaging User Guide provides additional official guidance on virtual environments and package installation.
Create the Code You Want to Test
Inside the project folder, create a file named calculator.py. Add a simple function:
def add(a, b):
return a + bThe function receives two values and returns their sum. You could open the Python interpreter and try several values manually, but we will create a test file that performs those checks automatically.
Write Your First Pytest Test
Create a second file in the same folder and name it test_calculator.py. The test_ prefix matters because Pytest uses naming conventions to discover test files automatically.
Add the following code:
from calculator import add
def test_add_two_numbers():
result = add(2, 3)
assert result == 5Here is what each part does:
from calculator import addimports the function being tested.def test_add_two_numbers()defines a test function.result = add(2, 3)runs the real application code.assert result == 5checks whether the result matches the expected value.
The test function also starts with test_. Pytest uses this naming pattern to find tests. Descriptive names are better than vague names such as test_1, because they immediately explain which behavior is being checked.
Run Your First Test
In the terminal, make sure you are inside the project folder and that the virtual environment is active. Then run:
pytestIf everything is correct, the output will look similar to this:
collected 1 item
test_calculator.py . [100%]
1 passedThe dot means the test passed. The message 1 passed confirms that Pytest found and successfully executed one test.
For more detailed output, use:
pytest -vThe -v option means verbose. It displays the full name of each test. For a shorter report, use:
pytest -qWhat Happens When a Test Fails?
One of Pytest’s strongest features is its readable failure report. Temporarily change the expected result to an incorrect value:
def test_add_two_numbers():
result = add(2, 3)
assert result == 6Run pytest again. The test will fail because adding 2 and 3 produces 5, not 6. You will see output similar to:
E assert 5 == 6
FAILED test_calculator.py::test_add_two_numbersPytest shows the actual value, the expected value, the test name, and the line where the comparison failed. This makes it easier to understand the problem than a simple generic error message.
A failed test does not automatically mean Pytest is broken. Usually, one of these situations is responsible:
- The application code contains a bug.
- The expected value in the test is incorrect.
- The test does not accurately represent the intended rule.
After reviewing the failure, change the expected result back to 5.
Add More Test Cases
A single test rarely covers every useful scenario. Add tests for negative numbers and zero:
from calculator import add
def test_add_two_numbers():
assert add(2, 3) == 5
def test_add_negative_number():
assert add(-2, 5) == 3
def test_add_zero():
assert add(10, 0) == 10Run pytest -v and Pytest will list all three tests separately. If one scenario fails, you will know exactly which behavior needs attention.
Keep tests focused. A small test that checks one behavior is usually easier to understand and maintain than a large test that performs many unrelated checks.
How to Test Exceptions with pytest.raises()
Not every test expects a function to return a value. Sometimes the correct behavior is to raise an exception. Add this function to calculator.py:
def divide(a, b):
if b == 0:
raise ValueError("The divisor cannot be zero")
return a / bNow update the test file:
import pytest
from calculator import add, divide
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(10, 0)The with pytest.raises(ValueError) block tells Pytest that the function is expected to raise a ValueError. The test passes when that exception occurs and fails when it does not.
This approach is useful for validation rules, file operations, conversions, and business logic. To understand the underlying exception-handling concepts, review this guide to try and except in Python.
You can also check the exception message:
def test_divide_by_zero_message():
with pytest.raises(ValueError, match="The divisor cannot be zero"):
divide(10, 0)How to Organize Test Files
For a very small project, source files and tests can stay in the same folder. As the project grows, a separate tests directory creates a clearer structure:
pytest_project/
├── calculator.py
└── tests/
└── test_calculator.pyRun Pytest from the pytest_project directory. By default, it searches the current folder and subfolders for files named like test_*.py or *_test.py.
Useful conventions include:
- Keep tests in a dedicated
testsfolder. - Start test filenames with
test_. - Start test function names with
test_. - Use names that describe the scenario.
- Keep application code separate from test code.
Consistent formatting also makes tests easier to scan. The overview of PEP 8 style guidelines covers practical conventions for readable Python code.
Useful Pytest Commands for Beginners
You do not need to memorize dozens of options. The following commands cover many common beginner workflows.
Run All Tests
pytestShow Test Names
pytest -vRun One Test File
pytest tests/test_calculator.pyRun Tests Whose Names Match a Word
pytest -k addThis command runs tests with add in their names.
Stop After the First Failure
pytest --maxfail=1Run Only Tests That Failed Last Time
pytest --lfThe --lf option means “last failed.” It is helpful when you are working on a specific problem and do not need to rerun every passing test.
Common Pytest Problems and Fixes
The pytest Command Is Not Recognized
Check that the virtual environment is active and that installation completed successfully. You can also run:
python -m pytestThis tells Python to load the installed module directly.
Pytest Finds No Tests
Make sure the filename starts with test_ or ends with _test.py. Test functions should also start with test_.
The Application Module Cannot Be Imported
Run the command from the project’s root folder. Check the module name and avoid spaces or hyphens in Python filenames.
Your File Is Named pytest.py
Do not name your own file pytest.py. It can shadow the real Pytest package and cause confusing import errors.
The Test Passes Without Checking Anything
Pytest can run a function whose name starts with test_ even when it contains no assertion. Make sure every test has a clear expectation, such as an assert statement or an expected exception.
The Failure Output Is Difficult to Understand
Run pytest -v and focus on the first failure. If necessary, use breakpoints and learn how to debug Python in VS Code.
Beginner-Friendly Testing Practices
Start with functions that accept inputs and return predictable outputs. These are usually easier to test than code that depends on network requests, files, databases, or user interfaces.
- Give every test a descriptive name.
- Test one main behavior per function.
- Include normal inputs, edge cases, and invalid values.
- Do not depend on the order in which tests run.
- Do not make one test depend on another test’s result.
- Run the suite after changing application code.
- Keep tests as readable as the code they verify.
A useful pattern for thinking about each test is:
- Arrange: prepare the required inputs or state.
- Act: call the function being tested.
- Assert: compare the result with the expectation.
In the first example, we arranged the values 2 and 3, acted by calling add, and asserted that the result was 5.
What to Learn After This Guide
Once the basics feel comfortable, you can explore features that reduce repetition and support larger projects:
- Fixtures: prepare reusable data and resources.
- Parametrization: run one test with several inputs.
- Mocks: replace external services or dependencies during tests.
- Coverage: show which lines of code were executed by tests.
- Continuous integration: run tests automatically when code is pushed.
You do not need to learn all of these topics at once. A small set of clear tests already provides real value and helps you build the habit of checking code continuously.
Conclusion
Pytest in Python provides a straightforward way to begin automated testing. Install the package, create files and functions whose names start with test_, use assert to compare results, and run the suite with the pytest command.
In this tutorial, you tested an addition function, inspected an intentional failure, covered multiple scenarios, and used pytest.raises() to verify an expected exception. You also learned a practical folder structure, useful commands, and common fixes.
As a next exercise, add subtraction, multiplication, and division functions to calculator.py. Write at least two tests for each function. That small project will help you understand the complete workflow before moving on to fixtures, parametrization, and mocks.






