Python24 min read
Python Testing with Pytest
Learn pytest to verify your code automatically, catch bugs early, and ship confidently using fixtures, parametrized tests, and mocking.
David Miller
September 12, 2025
4.2k177
Testing means: you write code that checks your code.
Why it matters:
- it prevents bugs
- it protects you when you refactor
- it makes your project trustworthy for teams and clients
Pytest is popular because it is:
- simple syntax
- powerful features
- easy to read and maintain
## Install pytest
```bash
pip install pytest
```
## Your first test (the pytest style)
Create a file named: `test_math.py`
```python
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
assert add(0, 0) == 0
assert add(-1, 1) == 0
```
Run:
```bash
pytest
```
### What is assert?
`assert` means: “This must be true.”
If false, the test fails.
## Test a class
```python
class Calculator:
def add(self, a, b):
return a + b
def multiply(self, a, b):
return a * b
def test_calculator():
calc = Calculator()
assert calc.add(2, 3) == 5
assert calc.multiply(2, 3) == 6
```
## Fixtures (setup for tests)
Fixtures are reusable setup functions.
```python
import pytest
@pytest.fixture
def sample_data():
return [1, 2, 3, 4, 5]
def test_sum(sample_data):
assert sum(sample_data) == 15
def test_length(sample_data):
assert len(sample_data) == 5
```
Benefit:
- no repeated setup code
- cleaner tests
## Parametrize (test many cases quickly)
```python
import pytest
def is_even(n):
return n % 2 == 0
@pytest.mark.parametrize("number,expected", [
(2, True),
(3, False),
(4, True),
(5, False)
])
def test_is_even(number, expected):
assert is_even(number) == expected
```
This is excellent for:
- edge cases
- boundary values
- input variations
## Testing exceptions
```python
import pytest
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(10, 0)
```
## Mocking (when external dependency exists)
Mocking helps when your function depends on:
- API calls
- database
- payment gateway
- file system
```python
from unittest.mock import Mock
def get_user_data(api):
return api.fetch_user(123)
def test_get_user_data():
mock_api = Mock()
mock_api.fetch_user.return_value = {"name": "Tom"}
result = get_user_data(mock_api)
assert result["name"] == "Tom"
```
## Graph: testing flow
```mermaid
flowchart LR
A[Write feature code] --> B[Write tests]
B --> C[Run pytest]
C --> D{All tests pass?}
D -->|Yes| E[Ship confidently]
D -->|No| F[Fix bug + rerun]
```
## Best practices (student-friendly)
- Write tests for your core logic first
- Add edge case tests (empty lists, None, zero, negative)
- Keep tests independent
- Use fixtures for setup
- Mock external services
## Remember
- Tests reduce bugs and fear of change
- pytest is simple: function name starts with test_
- Use fixtures for setup, parametrize for many cases
#Python#Advanced#Testing