I'm using the Django TestCase class for some of the conveniences - fixture loading, special assertions, etc - but I'd like to use some of the pytest fixtures if possible. I can use @pytest.mark.usefixtures but that doesn't to give me access to the objects returned by the fixtures, as far as I can tell. For example, if I use @pytest.mark.usefixtures("admin_client"), the admin client generated by the fixture isn't available anywhere that I can find.
Is there a way to do this that I'm missing? Or just something that's not supported?
I see in the pytest documentation that fixtures can be written to support working with unit test style TestCase classes - https://docs.pytest.org/en/latest/unittest.html#mixing-pytest-fixtures-into-unittest-testcase-subclasses-using-marks ; would that be an option for pytest-django fixtures?
@rlskoeser Yup, using the same strategy for Python unittest.TestCase as you would for django.test.TestCase works. You can either inject the pytest fixture(s) into the test class or instance, depending on what you need.
@gsong sorry, are you saying this works currently? Could you provide example code showing how I would access e.g. admin_client within a class?
@rlskoeser Have you tried something like:
import pytest
class TestOrders:
def test_create_order(self, admin_client):
response = admin_client.get('/myurl')
assert response.status_code == 200
Not sure if this is what you are looking for.
@rlskoeser Something like this:
from django.test import TestCase
import pytest
from ..client import MagicClient
@pytest.mark.usefixtures("inject_attrs")
class TestGetSubjectId(TestCase):
def test_something(self):
result = self.admin_client.do_something()
assert result is True
@pytest.fixture(scope="class")
def inject_attrs(request, admin_client):
request.cls.admin_client = admin_client
@pytest.fixture
def admin_client():
return MagicClient()
You can inject as many pytest fixtures as you want in the inject_attrs fixture. If you would rather attach the fixture to the TestCase instance, just use request.instance instead of request.cls.
Let me know if this isn't clear.
@gsong Thank you for your snippet! Unfortunately it looks like DB records of the objects created in the fixtures are not getting wiped out between calls, right? I mean if I have few test_... methods in my class, wrapped with @pytest.mark.usefixtures then the fixture get called for the each test method, but the DB is not getting cleaned.
UPD: That's because fixtures used in a class-decoration should be defined via @pytest.fixture(scope="class"), then everything is fine.
see also: #13 "Easy fixture loading"
Closing as answered.
Most helpful comment
@rlskoeser Something like this:
You can inject as many pytest fixtures as you want in the
inject_attrsfixture. If you would rather attach the fixture to theTestCaseinstance, just userequest.instanceinstead ofrequest.cls.Let me know if this isn't clear.