django-tenant-schemas icon indicating copy to clipboard operation
django-tenant-schemas copied to clipboard

Pytest Fixture to do same as TenantTestCase

Open softinio opened this issue 6 years ago • 12 comments

I would like to move our Django Project using this project to use Pytest for testing. Unfortunatley the current TenantTestCase and FastTenantTestCase does not work with Pytest as it doesn't create the tenant schema and tries to use public schema for everything.

See: https://github.com/pytest-dev/pytest-django/issues/633

Be great if a pytest fixture could be added to this project as an alternative to TenantTestCase so we can use pytest easily with this project.

I am happy to help with this issue and contribute this to the project but would like so guidance from the project owner if possible.

Many thanks.

softinio avatar Dec 22 '18 18:12 softinio

I'm using this project with pytest. It took some work to figure out how to set it up, but when I did it worked like a charm.

rj76 avatar Dec 24 '18 07:12 rj76

@rj76 any pointers or help appreciated on how you set it up appreciated. Thanks!

softinio avatar Dec 24 '18 07:12 softinio

I've created this gist, that should help you get setup:

https://gist.github.com/rj76/c33ee201428be26b9c78a78473b5b169

One thing to keep in mind, is that to use fixtures you must be sure to create them in the right tenant context. If you only use one tenant in your tests, it's easy to reuse them, but in my case I ended up not having many shared fixtures across app tests.

If you have any questions, let me know ;)

rj76 avatar Dec 24 '18 08:12 rj76

@rj76 thanks so much you are awesome will take a look. Happy New Year!

softinio avatar Jan 02 '19 22:01 softinio

I've created this gist, that should help you get setup:

https://gist.github.com/rj76/c33ee201428be26b9c78a78473b5b169

One thing to keep in mind, is that to use fixtures you must be sure to create them in the right tenant context. If you only use one tenant in your tests, it's easy to reuse them, but in my case I ended up not having many shared fixtures across app tests.

If you have any questions, let me know ;)

Richard, I've been struggling while trying to run pytest on my test_views.py. I was hoping you could point me in the right direction (examples, articles, etc) thanks in advance!

JohnnyFang avatar Jan 28 '19 17:01 JohnnyFang

Hi, I couldn't find much information on the interwebs, so I figured it out myself. Can you point out the problem you're facing?

rj76 avatar Jan 29 '19 06:01 rj76

I spent a little time tinkering with the excellent example (thanks @rj76 ! ) The big difference is that it's a little more annotated (there were a few intricacies I didn't get in the original example) , and that it by default runs all tests in the context of a tenant, so that regular tests "just work" - I'm migrating a couple of hundred tests to this library, and it was important for me to not have to change all my tests:

https://gist.github.com/GeeWee/54b6fd7ad87bcc876781ae02d1e0993d

GeeWee avatar Feb 04 '19 15:02 GeeWee

+1 I'm also looking to get this working with pytest. The TenantTestCase is great, but precludes pytest's fixtures and parameterization features.

dwcaraway avatar Feb 19 '19 19:02 dwcaraway

Did anyone find a solution to this?

softinio avatar Sep 05 '19 22:09 softinio

I've just updated my gist reference above to the version I am currently using day-to-day, and I'm happy to report it works without a hitch.

GeeWee avatar Sep 06 '19 05:09 GeeWee

I created another gist how I have done this using fixtures: https://gist.github.com/user37596/97e612f5c67adfad79105613af6204a6

Notice though, it is made for django-tenants package, not django-tenant-schemas, but it's not very hard to adapt the code to django-tenant-schemas.

With those fixtures in your conftest.py, you can create tests like:

# This test will happen with connection.tenant being non-public tenant.
def test_login(test_client):
    user = UserFactory()
    response = test_client.post("/login/", {"username": user.username, "password": user.password})
    assert response.status_code == 302

The test_client fixture makes sure non-public test tenant exists and is activated. If you want to test in the public tenant domain, use:

# This test will happen with connection.tenant being public tenant.
def test_login(public_test_client):
    user = UserFactory()
    response = public_test_client.post("/login/", {"username": user.username, "password": user.password})
    assert response.status_code == 302

akifd avatar Sep 26 '19 13:09 akifd

I've fixed it by setting up a public and pytest tenant before all tests run in the django_db_setup hook for pytest and setting the connection to the pytest tenant. See https://gist.github.com/jeroenbrouwer/61b419e7232710e95c3e9454c7c78863

The downside to this implementation is that everything really does happen on a DB (I use a separate test DB for this) and that the flush command has to work (or you should do some other manual clean-up). To get the flush command to work see https://github.com/bernardopires/django-tenant-schemas/pull/567

jeroenbrouwer avatar Dec 04 '19 07:12 jeroenbrouwer