Skip to content

Commit e452e08

Browse files
committed
Add fixtures for user request factories, clients
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. Also, Update fixtures.py with changes from @blueyed
1 parent 1183815 commit e452e08

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

pytest_django/fixtures.py

+102-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
__all__ = ['django_db_setup', 'db', 'transactional_db', 'admin_user',
1919
'django_user_model', 'django_username_field',
20-
'client', 'admin_client', 'rf', 'settings', 'live_server',
20+
'client', 'admin_client', 'user_client', 'rf', 'settings',
21+
'django_user', 'rf_unauth', 'rf_user', 'rf_admin', 'live_server',
2122
'_live_server_helper', 'django_assert_num_queries']
2223

2324

@@ -229,6 +230,36 @@ def admin_client(db, admin_user):
229230
return client
230231

231232

233+
@pytest.fixture()
234+
def django_user(db, django_user_model, django_username_field):
235+
"""A Django user.
236+
This uses an existing user with username "user", or creates a new one with
237+
password "password".
238+
"""
239+
UserModel = django_user_model
240+
username_field = django_username_field
241+
242+
try:
243+
user = UserModel._default_manager.get(**{username_field: 'user'})
244+
except UserModel.DoesNotExist:
245+
extra_fields = {}
246+
if username_field != 'username':
247+
extra_fields[username_field] = 'user'
248+
user = UserModel._default_manager.create_user(
249+
'user', '[email protected]', 'password', **extra_fields)
250+
return user
251+
252+
253+
@pytest.fixture()
254+
def user_client(db, django_user):
255+
"""A Django test client logged in as a normal user."""
256+
from django.test.client import Client
257+
258+
client = Client()
259+
client.login(username=django_user.username, password='password')
260+
return client
261+
262+
232263
@pytest.fixture()
233264
def rf():
234265
"""RequestFactory instance"""
@@ -239,6 +270,76 @@ def rf():
239270
return RequestFactory()
240271

241272

273+
@pytest.fixture
274+
def rf_unauth():
275+
"""Anonymous user request factory.
276+
277+
This does two things to the request object:
278+
279+
1. Adds an anonymous user per Django's doc examples on request
280+
factories:
281+
282+
https://docs.djangoproject.com/en/2.0/topics/testing/advanced/#example
283+
284+
This simiulates ``django.contrib.auth.middleware.AuthenticationMiddleware``.
285+
286+
2. Adds a naive session storage object to request.
287+
288+
This simiulates ``django.contrib.sessions.middleware.SessionMiddleware``,
289+
and prevents errors on stuff like SessionWizardView in django-formtools.
290+
"""
291+
from django.test.client import RequestFactory
292+
from django.contrib.auth.models import AnonymousUser
293+
from django.contrib.sessions.backends.base import SessionBase
294+
295+
class UnauthRequestFactory(RequestFactory):
296+
def request(self, **request):
297+
r = super(UnauthRequestFactory, self).request(**request)
298+
r.user = AnonymousUser()
299+
r.session = SessionBase()
300+
return r
301+
302+
return UnauthRequestFactory()
303+
304+
305+
@pytest.fixture
306+
def rf_admin(admin_user):
307+
"""Admin user request facctory.
308+
309+
Mimics AuthenticationMiddleware. Also adds a memory-backed session store
310+
to the request object."""
311+
from django.test.client import RequestFactory
312+
from django.contrib.sessions.backends.base import SessionBase
313+
314+
class AdminRequestFactory(RequestFactory):
315+
def request(self, **request):
316+
r = super(AdminRequestFactory, self).request(**request)
317+
r.user = admin_user
318+
r.session = SessionBase()
319+
return r
320+
321+
return AdminRequestFactory()
322+
323+
324+
@pytest.fixture
325+
def rf_user(django_user):
326+
"""Normal user request factory.
327+
328+
Mimics AuthenticationMiddleware. Also adds a memory-backed session store
329+
to the request object."""
330+
from django.test.client import RequestFactory
331+
from django.contrib.sessions.backends.base import SessionBase
332+
333+
class UserRequestFactory(RequestFactory):
334+
def request(self, **request):
335+
r = super(UserRequestFactory, self).request(**request)
336+
r.user = django_user
337+
r.session = SessionBase()
338+
return r
339+
340+
return UserRequestFactory()
341+
342+
242343
class SettingsWrapper(object):
243344
_to_restore = []
244345

pytest_django/plugin.py

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .fixtures import django_db_createdb # noqa
2323
from .fixtures import django_db_modify_db_settings # noqa
2424
from .fixtures import django_db_modify_db_settings_xdist_suffix # noqa
25+
from .fixtures import django_user # noqa
2526
from .fixtures import _live_server_helper # noqa
2627
from .fixtures import admin_client # noqa
2728
from .fixtures import admin_user # noqa
@@ -31,8 +32,12 @@
3132
from .fixtures import django_username_field # noqa
3233
from .fixtures import live_server # noqa
3334
from .fixtures import rf # noqa
35+
from .fixtures import rf_admin # noqa
36+
from .fixtures import rf_user # noqa
37+
from .fixtures import rf_unauth # noqa
3438
from .fixtures import settings # noqa
3539
from .fixtures import transactional_db # noqa
40+
from .fixtures import user_client # noqa
3641
from .pytest_compat import getfixturevalue
3742

3843
from .lazy_django import django_settings_is_configured, skip_if_no_django

0 commit comments

Comments
 (0)