How do I correctly setup and teardown for my pytest class with tests?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In pytest, class-based setup and teardown works, but fixtures are usually the cleaner tool. The right choice depends on whether you need per-test state, per-class shared resources, or explicit old-style hooks for a small test class.
Prefer Fixtures for Most Setup Logic
Pytest fixtures are the normal way to prepare resources and clean them up. A fixture can return data to each test and use yield so teardown happens automatically afterward.
Here is a function-scoped example that runs once per test:
Each test gets a fresh fixture value, which keeps tests isolated. That isolation is one of the biggest reasons fixtures are preferred over mutable shared class state.
Use Class-Scoped Fixtures for Shared Expensive Resources
If setup is expensive and can be shared safely across tests in one class, use a fixture with scope="class".
This runs the setup once for the class and tears it down once after the final test in that class. It is a good fit for temporary databases, service clients, or other shared but controlled resources.
xUnit-Style Hooks Still Work
Pytest also supports classic hooks such as setup_method, teardown_method, setup_class, and teardown_class.
These hooks are fine for simple cases, especially when porting old unittest-style code. The limitation is that they are less composable than fixtures and do not integrate as naturally with dependency injection across the test suite.
Choose Based on Scope
A good rule is:
- use function-scoped fixtures for per-test state
- use class-scoped fixtures for expensive shared setup
- use xUnit hooks only when they genuinely make the class clearer
That approach keeps tests readable and avoids accidental coupling between methods.
Avoid Sharing Mutable State Unless Necessary
One of the biggest mistakes in class-based test code is storing mutable state on self or cls and then letting tests depend on previous tests having run first.
Bad pattern:
This suite is order-sensitive. That is exactly what pytest tries to help you avoid.
Common Pitfalls
- Using class variables for mutable shared state when tests really need fresh data per method.
- Writing teardown code that never runs because the setup raised an exception before the cleanup path was structured correctly.
- Choosing xUnit hooks by habit even when fixtures would be more reusable and explicit.
- Assuming
selfpersists between tests in pytest. Each test method gets a new instance. - Building tests that depend on execution order instead of isolated setup.
Summary
- In pytest, fixtures are usually the best way to handle setup and teardown.
- Use function-scoped fixtures for isolated per-test resources.
- Use class-scoped fixtures when setup is expensive and safe to share within a class.
- xUnit-style hooks such as
setup_methodstill work, but they are usually less flexible than fixtures. - Keep tests isolated and avoid mutable shared state unless there is a strong reason to share it.

