what is it?
- Functions that can be run before/after each test which the fixture is applied to
- Feeds data to the test
- Usually applied in the arrange phase of testing
- builtin fixture, examples: caplog, monkeypatch
built-in and plugin fixtures
to see a list of pytest fixtures available:
pytest --fixtures
monkeypatch
transactional_db
akin to using Django’s TransactionTestCase
- adds transaction support to the test
- without it, each test is wrapped in a transaction, which is then rolled back after each test
- no transactions are ever committed, so
on_commit()never runs
- no transactions are ever committed, so
- to test code fired in an
on_commitcallback within pytest, you can use thetransactional_dbfixture - slow.. to just test
on_commit, you can rather use the django_capture_on_commit_callbacks fixture
client
used to send requests to our Django view
tmpdir
return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory.
settings
a django settings object which restores changes after the testrun
custom fixtures
import pytest
@pytest.fixture
def fixture_1():
return 1
def test_example(fixture_1):
num = fixture_1
assert num == 1autouse
a convenient way to make all tests automatically request them. This can cut out a lot of redundant requests
@pytest.fixture(autouse=True)
def append_first(order, first_entry):
return order.append(first_entry)scope
Defining a scope, changes the way it runs
import pytest
@pytest.fixture(scope=session)
def fixture_1():
return 1- function(default) - once per test
- class - once per class of tests
- module - once per module
- session - once per session
yield vs return
to run a fixture at the end of a test (yield vs return)
import pytest
@pytest.fixture()
def yield_fixture():
print("Start Test Phase")
yield 6
print("End Test Phase")
def test_example(yield_fixture):
print("run-example-1")
assert yield_fixture == 6
conftest.py
it’s better to move custom fixtures into tests/conftest.py instead of adding it to the test_<APP> files
import pytest
from django.contrib.auth.models import User
@pytest.fixture()
def user_1(db):
user = User.objects.create_user("test-user")
print('create-user')
return userfactory
factory to re-use fixture for, for example different user roles:
import pytest
from django.contrib.auth.models import User
@pytest.fixture
def new_user_factory(db):
def create_app_user(
username: str,
password: str = None,
first_name: str = "firstname",
last_name: str = "lastname",
email: str = "[email protected]",
is_staff: str = False,
is_superuser: str = False,
is_active: str = True,
):
user = User.objects.create_user(
username=username,
password=password,
first_name=first_name,
last_name=last_name,
email=email,
is_staff=is_staff,
is_superuser=is_superuser,
is_active=is_active,
)
return user
return create_app_user
@pytest.fixture
def new_user1(db, new_user_factory):
return new_user_factory("Test_user","password","MyName")
@pytest.fixture
def new_user2(db, new_user_factory):
return new_user_factory("Test_user","password", "MyName", is_staff="True")