Skip to content

Testing with pytest

If you know jest, pytest will feel familiar in structure but delightfully simpler in syntax. No .toBe(), no expect() wrappers — pytest uses plain Python assert statements and its magic rewrites them to show helpful diffs on failure.

Run this in your terminal:

Terminal window
pip install pytest
# or:
uv add --dev pytest
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run a specific file
pytest tests/test_math.py
# Run a specific test by name
pytest tests/test_math.py::test_add
TypeScript
// jest — TypeScript
import { add, greet } from './math';
describe('math utils', () => {
test('adds two numbers', () => {
expect(add(2, 3)).toBe(5);
});
test('greet returns a string', () => {
expect(greet('Alice')).toBe('Hello, Alice!');
});
test('throws on negative input', () => {
expect(() => add(-1, 0)).toThrow('negative');
});
});
Python
# pytest — Python
# File must start with test_ or end with _test.py
# Functions must start with test_
from math_utils import add, greet
import pytest
def test_adds_two_numbers():
assert add(2, 3) == 5
def test_greet_returns_string():
assert greet("Alice") == "Hello, Alice!"
def test_raises_on_negative_input():
with pytest.raises(ValueError, match="negative"):
add(-1, 0)

pytest finds tests automatically — no test runner config needed to get started:

Rulepytestjest
File patterntest_*.py or *_test.py*.test.ts or *.spec.ts
Function patterntest_*test(...) or it(...)
Class patternTest* (no __init__)describe(...)
Setupsetup_method / fixturesbeforeEach
Teardownteardown_method / fixturesafterEach

In jest you use beforeEach / afterEach. pytest uses fixtures: dependency-injected functions that set up and optionally tear down resources. They are more powerful than beforeEach because they compose and have controlled scopes.

TypeScript
// jest beforeEach
let db: MockDatabase;
beforeEach(() => {
db = new MockDatabase();
db.seed([{ id: 1, name: 'Alice' }]);
});
afterEach(() => {
db.close();
});
test('finds a user', () => {
expect(db.find(1)).toEqual({ id: 1, name: 'Alice' });
});
Python
# pytest fixture — equivalent to beforeEach/afterEach
import pytest
@pytest.fixture
def db():
database = MockDatabase()
database.seed([{"id": 1, "name": "Alice"}])
yield database # test runs here
database.close() # teardown after yield
def test_finds_a_user(db): # pytest injects the fixture
assert db.find(1) == {"id": 1, "name": "Alice"}
TypeScript
// jest — test.each for data-driven tests
test.each([
[1, 2, 3],
[0, 0, 0],
[-1, 1, 0],
])('add(%i, %i) = %i', (a, b, expected) => {
expect(add(a, b)).toBe(expected);
});
Python
# pytest — @pytest.mark.parametrize
import pytest
@pytest.mark.parametrize("a, b, expected", [
(1, 2, 3),
(0, 0, 0),
(-1, 1, 0),
])
def test_add(a, b, expected):
assert add(a, b) == expected
# pytest-style assertions work in plain Python too
def add(a: int, b: int) -> int:
return a + b
def test_basic():
assert add(2, 3) == 5
assert add(0, 0) == 0
def test_string():
message = "Hello, World!"
assert "World" in message
assert message.startswith("Hello")
assert len(message) == 13
# Run the tests manually
test_basic()
test_string()
print("All assertions passed!")

Playground note: The snippet above shows Python’s plain assert statements. The full pytest runner (test discovery, fixtures, parametrize, --cov) requires a terminal with pytest installed. Run pytest -v in your project to see the real experience.

By default, pytest discovers test functions in files that match which pattern?
What is the pytest equivalent of jest's beforeEach / afterEach pattern?
How do you write an assertion in pytest?
Which decorator enables data-driven (parametrized) tests in pytest?