The pytest-pyspec plugin transforms pytest output into a beautiful, readable format similar to RSpec. It provides semantic meaning to your tests by organizing them into descriptive hierarchies, using the prefixes Describe/Test, With/Without/When, and test_/it_, while allowing docstrings and decorators to override the descriptions.
- Semantic Output: Transform pytest's default output into readable, hierarchical descriptions
- Multiple Prefixes: Support for
describe/test(objects),with/without/when(contexts), andit/test(tests) - Docstring Support: Override test descriptions using docstrings
- Consolidated Output: Smart grouping that avoids repeating parent headers
- Natural Language: Automatic lowercase formatting of common words (the, is, are, etc.)
- Decorator Support: Override descriptions right next to your classes and tests
pip install pytest pytest-pyspecpytest --pyspecA minimal car example with properties and behaviors:
class DescribeCar: def test_has_engine(self): assert True class WithFullTank: def test_drive_long_distance(self): assert True class WithoutFuel: def test_cannot_start_engine(self): assert True class WhenTheEngineIsRunning: def test_consumes_fuel(self): assert TrueWith pytest-pyspec, this produces:
a Car ✓ has engine with Full Tank ✓ drive long distance without Fuel ✓ cannot start engine when the Engine is Running ✓ consumes fuel pytest-pyspec supports three types of prefixes to create semantic test hierarchies:
Define what you're testing:
class DescribeCar: # or class TestCar: def test_has_four_wheels(self): assert TrueOutput:
a Car ✓ has four wheels Define the context or state:
class DescribeCar: class WithFullTank: def test_can_drive_long_distances(self): assert True class WithoutFuel: def test_cannot_start_engine(self): assert True class WhenTheEngineIsRunning: def test_consumes_fuel(self): assert TrueOutput:
a Car with Full Tank ✓ can drive long distances without Fuel ✓ cannot start engine when the Engine is Running ✓ consumes fuel Define the expected behavior:
class DescribeCar: def it_has_four_wheels(self): assert True def test_has_engine(self): assert TrueOutput:
a Car ✓ has four wheels ✓ has engine Override automatic naming with custom descriptions:
class TestCar: """sports car""" def test_top_speed(self): """reaches 200 mph""" assert True class WhenTheNitroIsActivated: """when nitro boost is activated""" def test_acceleration(self): """accelerates rapidly""" assert TrueOutput:
a sports car ✓ reaches 200 mph when nitro boost is activated ✓ accelerates rapidly Prefer decorators over docstrings? Import the helpers directly from pytest_pyspec:
import pytest_pyspec as spec @spec.describe("Car") class DescribeCar: @spec.it("reaches 200 mph") def test_top_speed(self): assert True @spec.when("nitro boost is activated") class WhenTheNitroIsActivated: @spec.it("accelerates rapidly") def test_acceleration(self): assert TrueOutput:
a Car ✓ reaches 200 mph when nitro boost is activated ✓ accelerates rapidly You can also import individual helpers (describe, with_, without, when, it) directly from pytest_pyspec if you prefer from ... import ... style. with is still exposed as with_ because the plain name is reserved.
Decorators always win when both a docstring and a decorator are present, so you can keep docstrings for documentation/IDE help while letting decorators drive runtime output.
The plugin is automatically enabled when you use the --pyspec flag. No additional configuration is required.
For more information, see the documentation.