Skip to content

Commit

Permalink
Add fixtures for user request factories, clients
Browse files Browse the repository at this point in the history
Fixes pytest-dev#565

This is based on conversations in issues pytest-dev#553, pytest-dev#554, and pytest-dev#284

- Introduces a django_user fixture, which is a user with no additional
  priveleges. Similar to admin_user.
- A user_client, based on django_user. Similar to admin_client.
- 3 new RequestFactory based fixtures, for unauthenticated,
  authenticated, and admin users:

  - rf_unauth: relies on AnonymousUser, similar to django docs
    example.
  - rf_admin: relies on admin_user fixture
  - rf_user: relies on new django_user fixture

  In addition, these 3 fixtures differ from rf in that they:

  - Mimic AuthenticationMiddleware by add the user attribute to
    the request object
  - Mimic SessionMiddleware by adding the 'session' attribute
    to the request object. This is an in-memory session store object
    from ``django.contrib.sessions.backends.base.SessionBase``.

This fills the gaps left over by not having normal and unauthenticated
user objects, clients, and request factories (when admin ones were
available), and also covers a common case likely present in Django
projects - anonymous (not logged in), authenticated, and admin users.
  • Loading branch information
tony committed Dec 26, 2017
1 parent 0fde43b commit 83ace67
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
103 changes: 102 additions & 1 deletion pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

__all__ = ['django_db_setup', 'db', 'transactional_db', 'admin_user',
'django_user_model', 'django_username_field',
'client', 'admin_client', 'rf', 'settings', 'live_server',
'client', 'admin_client', 'user_client', 'rf', 'settings',
'django_user', 'rf_unauth', 'rf_user', 'rf_admin', 'live_server',
'_live_server_helper', 'django_assert_num_queries']


Expand Down Expand Up @@ -229,6 +230,36 @@ def admin_client(db, admin_user):
return client


@pytest.fixture()
def django_user(db, django_user_model, django_username_field):
"""A Django user.
This uses an existing user with username "user", or creates a new one with
password "password".
"""
UserModel = django_user_model
username_field = django_username_field

try:
user = UserModel._default_manager.get(**{username_field: 'user'})
except UserModel.DoesNotExist:
extra_fields = {}
if username_field != 'username':
extra_fields[username_field] = 'user'
user = UserModel._default_manager.create_user(
'user', 'user@example.com', 'password', **extra_fields)
return user


@pytest.fixture()
def user_client(db, django_user):
"""A Django test client logged in as an admin user."""
from django.test.client import Client

client = Client()
client.login(username=django_user.username, password='password')
return client


@pytest.fixture()
def rf():
"""RequestFactory instance"""
Expand All @@ -239,6 +270,76 @@ def rf():
return RequestFactory()


@pytest.fixture
def rf_unauth():
"""Anonymous user request factory.
This does two things to the request object:
1. Adds an anonymous user per Django's doc examples on request
factories:
https://docs.djangoproject.com/en/2.0/topics/testing/advanced/#example
This simiulates 'django.contrib.auth.middleware.AuthenticationMiddleware'
2. Add's a naive session storage object to request.
This simiulates 'django.contrib.sessions.middleware.SessionMiddleware',
and prevents errors on stuff like SessionWizardView in django-formtools.
"""
from django.test.client import RequestFactory
from django.contrib.auth.models import AnonymousUser
from django.contrib.sessions.backends.base import SessionBase

class UnauthRequestFactory(RequestFactory):
def request(self, **request):
r = super().request(**request)
r.user = AnonymousUser()
r.session = SessionBase()
return r

return UnauthRequestFactory()


@pytest.fixture
def rf_admin(admin_user):
"""Admin user request facctory.
Mimics AuthenticationMiddleware. Also adds a memory-backed session store
to the request object."""
from django.test.client import RequestFactory
from django.contrib.sessions.backends.base import SessionBase

class AdminRequestFactory(RequestFactory):
def request(self, **request):
r = super().request(**request)
r.user = admin_user
r.session = SessionBase()
return r

return AdminRequestFactory()


@pytest.fixture
def rf_user(django_user):
"""Normal user request facctory.
Mimics AuthenticationMiddleware. Also adds a memory-backed session store
to the request object."""
from django.test.client import RequestFactory
from django.contrib.sessions.backends.base import SessionBase

class UserRequestFactory(RequestFactory):
def request(self, **request):
r = super().request(**request)
r.user = django_user
r.session = SessionBase()
return r

return UserRequestFactory()


class SettingsWrapper(object):
_to_restore = []

Expand Down
5 changes: 5 additions & 0 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .fixtures import django_db_createdb # noqa
from .fixtures import django_db_modify_db_settings # noqa
from .fixtures import django_db_modify_db_settings_xdist_suffix # noqa
from .fixtures import django_user # noqa
from .fixtures import _live_server_helper # noqa
from .fixtures import admin_client # noqa
from .fixtures import admin_user # noqa
Expand All @@ -31,8 +32,12 @@
from .fixtures import django_username_field # noqa
from .fixtures import live_server # noqa
from .fixtures import rf # noqa
from .fixtures import rf_admin # noqa
from .fixtures import rf_user # noqa
from .fixtures import rf_unauth # noqa
from .fixtures import settings # noqa
from .fixtures import transactional_db # noqa
from .fixtures import user_client # noqa
from .pytest_compat import getfixturevalue

from .lazy_django import django_settings_is_configured, skip_if_no_django
Expand Down

0 comments on commit 83ace67

Please sign in to comment.