Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Prefix all fixtures with "django_" #711

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions docs/database.rst
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,12 @@ django_db_blocker

.. warning::
It does not manage transactions and changes made to the database will not
be automatically restored. Using the ``pytest.mark.django_db`` marker
or :fixture:`db` fixture, which wraps database changes in a transaction and
restores the state is generally the thing you want in tests. This marker
can be used when you are trying to influence the way the database is
configured.
be automatically restored.
Using the ``pytest.mark.django_db`` marker (or the corresponding
:fixture:`django_db` fixture) is usually what you want to use in test -
they will wrap database changes in a transaction and restore the state.
This marker can be used when you are trying to influence the way the
database is configured.

Database access is by default not allowed. ``django_db_blocker`` is the object
which can allow specific code paths to have access to the database. This
Expand Down
87 changes: 44 additions & 43 deletions docs/helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ More information on fixtures is available in the `pytest documentation
<https://pytest.org/en/latest/fixture.html>`_.


``rf`` - ``RequestFactory``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
``django_rf`` - ``RequestFactory``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An instance of a `django.test.RequestFactory`_

Expand All @@ -127,13 +127,13 @@ Example

from myapp.views import my_view

def test_details(rf):
request = rf.get('/customer/details')
def test_details(django_rf):
request = django_rf.get('/customer/details')
response = my_view(request)
assert response.status_code == 200

``client`` - ``django.test.Client``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``django_client`` - ``django.test.Client``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An instance of a `django.test.Client`_

Expand All @@ -144,25 +144,25 @@ Example

::

def test_with_client(client):
response = client.get('/')
def test_with_client(django_client):
response = django_client.get('/')
assert response.content == 'Foobar'

To use `client` as an authenticated standard user, call its `login()` method before accessing a URL:

::

def test_with_authenticated_client(client, django_user_model):
def test_with_authenticated_client(django_client, django_user_model):
username = "user1"
password = "bar"
django_user_model.objects.create_user(username=username, password=password)
client.login(username=username, password=password)
response = client.get('/private')
response = django_client.get('/private')
assert response.content == 'Protected Area'


``admin_client`` - ``django.test.Client`` logged in as admin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``django_admin_client`` - ``django.test.Client`` logged in as admin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An instance of a `django.test.Client`_, logged in as an admin user.

Expand All @@ -171,23 +171,23 @@ Example

::

def test_an_admin_view(admin_client):
response = admin_client.get('/admin/')
def test_an_admin_view(django_admin_client):
response = adjango_dmin_client.get('/admin/')
assert response.status_code == 200

Using the `admin_client` fixture will cause the test to automatically be marked for database use (no need to specify the
``django_db`` mark).
Using the `django_admin_client` fixture will cause the test to automatically be
marked for database use (no need to specify the ``django_db`` mark).

.. fixture:: admin_user

``admin_user`` - an admin user (superuser)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``django_admin_user`` - an admin user (superuser)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An instance of a superuser, with username "admin" and password "password" (in
case there is no "admin" user yet).

Using the `admin_user` fixture will cause the test to automatically be marked for database use (no need to specify the
``django_db`` mark).
Using the `django_admin_user` fixture will cause the test to automatically be
marked for database use (no need to specify the ``django_db`` mark).


``django_user_model``
Expand All @@ -213,18 +213,18 @@ This fixture extracts the field name used for the username on the user model, i.
``settings.USERNAME_FIELD``. Use this fixture to make pluggable apps testable regardless what the username field
is configured to be in the containing Django project.

``db``
~~~~~~~
``django_db``
~~~~~~~~~~~~~

.. fixture:: db
.. fixture:: django_db

This fixture will ensure the Django database is set up. Only
required for fixtures that want to use the database themselves. A
test function should normally use the ``pytest.mark.django_db``
mark to signal it needs the database.

``transactional_db``
~~~~~~~~~~~~~~~~~~~~
``django_transactional_db``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

This fixture can be used to request access to the database including
transaction support. This is only required for fixtures which need
Expand All @@ -242,13 +242,13 @@ sequences (if your database supports it). This is only required for
fixtures which need database access themselves. A test function should
normally use the ``pytest.mark.django_db`` mark with ``transaction=True`` and ``reset_sequences=True``.

``live_server``
~~~~~~~~~~~~~~~
``django_live_server``
~~~~~~~~~~~~~~~~~~~~~~

This fixture runs a live Django server in a background thread. The
server's URL can be retrieved using the ``live_server.url`` attribute
or by requesting it's string value: ``unicode(live_server)``. You can
also directly concatenate a string to form a URL: ``live_server +
server's URL can be retrieved using the ``django_live_server.url`` attribute
or by requesting it's string value: ``unicode(django_live_server)``. You can
also directly concatenate a string to form a URL: ``django_live_server +
'/foo``.

.. note:: Combining database access fixtures.
Expand All @@ -260,11 +260,11 @@ also directly concatenate a string to form a URL: ``live_server +
* ``transactional_db``
* ``django_db_reset_sequences``

In addition, using ``live_server`` will also trigger transactional
In addition, using ``django_live_server`` will also trigger transactional
database access, if not specified.

``settings``
~~~~~~~~~~~~
``django_settings``
~~~~~~~~~~~~~~~~~~~

This fixture will provide a handle on the Django settings module, and
automatically revert any changes made to the settings (modifications, additions
Expand All @@ -275,9 +275,9 @@ Example

::

def test_with_specific_settings(settings):
settings.USE_TZ = True
assert settings.USE_TZ
def test_with_specific_settings(django_settings):
django_settings.USE_TZ = True
assert django_settings.USE_TZ


.. fixture:: django_assert_num_queries
Expand Down Expand Up @@ -333,8 +333,8 @@ Example usage::
Item.objects.create('bar')


``mailoutbox``
~~~~~~~~~~~~~~
``django_mailoutbox``
~~~~~~~~~~~~~~~~~~~~~

A clean email outbox to which Django-generated emails are sent.

Expand All @@ -345,10 +345,10 @@ Example

from django.core import mail

def test_mail(mailoutbox):
def test_mail(django_mailoutbox):
mail.send_mail('subject', 'body', '[email protected]', ['[email protected]'])
assert len(mailoutbox) == 1
m = mailoutbox[0]
assert len(django_mailoutbox) == 1
m = django_mailoutbox[0]
assert m.subject == 'subject'
assert m.body == 'body'
assert m.from_email == '[email protected]'
Expand Down Expand Up @@ -379,5 +379,6 @@ Clearing of mail.outbox
~~~~~~~~~~~~~~~~~~~~~~~

``mail.outbox`` will be cleared for each pytest, to give each new test an empty
mailbox to work with. However, it's more "pytestic" to use the ``mailoutbox`` fixture described above
than to access ``mail.outbox``.
mailbox to work with.
However, it's more "pytestic" to use the ``django_mailoutbox`` fixture
described above than to access ``mail.outbox``.
32 changes: 16 additions & 16 deletions pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@

__all__ = [
"django_db_setup",
"db",
"transactional_db",
"django_db",
"django_transactional_db",
"django_db_reset_sequences",
"admin_user",
"django_admin_user",
"django_user_model",
"django_username_field",
"client",
"admin_client",
"rf",
"settings",
"live_server",
"django_client",
"django_admin_client",
"django_rf",
"django_settings",
"django_live_server",
"_live_server_helper",
"django_assert_num_queries",
"django_assert_max_num_queries",
Expand Down Expand Up @@ -157,7 +157,7 @@ def _disable_native_migrations():


@pytest.fixture(scope="function")
def db(request, django_db_setup, django_db_blocker):
def django_db(request, django_db_setup, django_db_blocker):
"""Require a django test database.

This database will be setup with the default fixtures and will have
Expand All @@ -183,7 +183,7 @@ def db(request, django_db_setup, django_db_blocker):


@pytest.fixture(scope="function")
def transactional_db(request, django_db_setup, django_db_blocker):
def django_transactional_db(request, django_db_setup, django_db_blocker):
"""Require a django test database with transaction support.

This will re-initialise the django database for each test and is
Expand Down Expand Up @@ -220,7 +220,7 @@ def django_db_reset_sequences(request, django_db_setup, django_db_blocker):


@pytest.fixture()
def client():
def django_client():
"""A Django test client instance."""
skip_if_no_django()

Expand All @@ -244,7 +244,7 @@ def django_username_field(django_user_model):


@pytest.fixture()
def admin_user(db, django_user_model, django_username_field):
def django_admin_user(db, django_user_model, django_username_field):
"""A Django admin user.

This uses an existing user with username "admin", or creates a new one with
Expand All @@ -267,7 +267,7 @@ def admin_user(db, django_user_model, django_username_field):


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

Expand All @@ -277,7 +277,7 @@ def admin_client(db, admin_user):


@pytest.fixture()
def rf():
def django_rf():
"""RequestFactory instance"""
skip_if_no_django()

Expand Down Expand Up @@ -320,7 +320,7 @@ def finalize(self):


@pytest.yield_fixture()
def settings():
def django_settings():
"""A Django settings object which restores changes after the testrun"""
skip_if_no_django()

Expand All @@ -330,7 +330,7 @@ def settings():


@pytest.fixture(scope="session")
def live_server(request):
def django_live_server(request):
"""Run a live Django server in the background during tests

The address the server is started from is taken from the
Expand Down
42 changes: 34 additions & 8 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@
from .fixtures import django_db_modify_db_settings # noqa
from .fixtures import django_db_modify_db_settings_xdist_suffix # noqa
from .fixtures import _live_server_helper # noqa
from .fixtures import admin_client # noqa
from .fixtures import admin_user # noqa
from .fixtures import client # noqa
from .fixtures import db # noqa
from .fixtures import django_admin_client # noqa
from .fixtures import django_admin_user # noqa
from .fixtures import django_client # noqa
from .fixtures import django_db # noqa
from .fixtures import django_user_model # noqa
from .fixtures import django_username_field # noqa
from .fixtures import live_server # noqa
from .fixtures import django_live_server # noqa
from .fixtures import django_db_reset_sequences # noqa
from .fixtures import rf # noqa
from .fixtures import settings # noqa
from .fixtures import transactional_db # noqa
from .fixtures import django_rf # noqa
from .fixtures import django_settings # noqa
from .fixtures import django_transactional_db # noqa
import warnings


from .lazy_django import django_settings_is_configured, skip_if_no_django

Expand All @@ -44,6 +46,30 @@
import pathlib2 as pathlib


# For backward compatibility.
class PytestDjangoPrefixDeprecationWarning(DeprecationWarning):
pass


def wrap_deprecated_fixture(oldname, newname):
@pytest.fixture(name=oldname)
def inner(request):
msg = "Please use fixture %s instead of %s." % (newname, oldname)
warnings.warn(PytestDjangoPrefixDeprecationWarning(msg))
return request.getfixturevalue(newname)
return inner


admin_client = wrap_deprecated_fixture("admin_client", "django_admin_client")
admin_user = wrap_deprecated_fixture("admin_user", "django_admin_user")
client = wrap_deprecated_fixture("client", "django_client")
db = wrap_deprecated_fixture("db", "django_db")
live_server = wrap_deprecated_fixture("live_server", "django_live_server")
rf = wrap_deprecated_fixture("rf", "django_rf")
settings = wrap_deprecated_fixture("settings", "django_settings")
transactional_db = wrap_deprecated_fixture("transactional_db", "django_transactional_db")


SETTINGS_MODULE_ENV = "DJANGO_SETTINGS_MODULE"
CONFIGURATION_ENV = "DJANGO_CONFIGURATION"
INVALID_TEMPLATE_VARS_ENV = "FAIL_INVALID_TEMPLATE_VARS"
Expand Down