From 4a4b8138c692b5565089cdf23b0e9fa6eeeab01d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 15 Mar 2019 01:40:50 +0100 Subject: [PATCH 1/4] Prefix all fixtures with "django_" --- pytest_django/fixtures.py | 32 ++++++++++++++++---------------- pytest_django/plugin.py | 28 ++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index 8bfc7da70..a487349f9 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -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", @@ -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 @@ -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 @@ -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() @@ -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 @@ -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 @@ -277,7 +277,7 @@ def admin_client(db, admin_user): @pytest.fixture() -def rf(): +def django_rf(): """RequestFactory instance""" skip_if_no_django() @@ -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() @@ -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 diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 09c61c801..c40e91da5 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -24,17 +24,18 @@ 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 +from .fixtures import django_transactional_db # noqa + from .lazy_django import django_settings_is_configured, skip_if_no_django @@ -44,6 +45,17 @@ import pathlib2 as pathlib +# For backward compatibility. +admin_client = django_admin_client +admin_user = django_admin_user +client = django_client +db = django_db +live_server = django_live_server +rf = django_rf +settings = django_settings +transactional_db = django_transactional_db + + SETTINGS_MODULE_ENV = "DJANGO_SETTINGS_MODULE" CONFIGURATION_ENV = "DJANGO_CONFIGURATION" INVALID_TEMPLATE_VARS_ENV = "FAIL_INVALID_TEMPLATE_VARS" From b03f730fdcf8320265cc69eca4f05c691119ec27 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 16 Mar 2019 03:53:14 +0100 Subject: [PATCH 2/4] docs --- docs/helpers.rst | 87 ++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/docs/helpers.rst b/docs/helpers.rst index 1685b70d0..1b5bc0a56 100644 --- a/docs/helpers.rst +++ b/docs/helpers.rst @@ -113,8 +113,8 @@ More information on fixtures is available in the `pytest documentation `_. -``rf`` - ``RequestFactory`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``django_rf`` - ``RequestFactory`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An instance of a `django.test.RequestFactory`_ @@ -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`_ @@ -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. @@ -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`` @@ -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 @@ -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. @@ -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 @@ -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 @@ -333,8 +333,8 @@ Example usage:: Item.objects.create('bar') -``mailoutbox`` -~~~~~~~~~~~~~~ +``django_mailoutbox`` +~~~~~~~~~~~~~~~~~~~~~ A clean email outbox to which Django-generated emails are sent. @@ -345,10 +345,10 @@ Example from django.core import mail - def test_mail(mailoutbox): + def test_mail(django_mailoutbox): mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com']) - 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 == 'from@example.com' @@ -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``. From 7a08fc0d180e3bcbb14159ecfeedefa03dac3f7d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 19 Mar 2019 05:02:46 +0100 Subject: [PATCH 3/4] Add PytestDjangoPrefixDeprecationWarning Not meant to be released necessarily, but to test it. --- pytest_django/plugin.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index c40e91da5..d7a495bb1 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -33,8 +33,9 @@ from .fixtures import django_live_server # noqa from .fixtures import django_db_reset_sequences # noqa from .fixtures import django_rf # noqa -from .fixtures import django_settings +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 @@ -46,14 +47,27 @@ # For backward compatibility. -admin_client = django_admin_client -admin_user = django_admin_user -client = django_client -db = django_db -live_server = django_live_server -rf = django_rf -settings = django_settings -transactional_db = django_transactional_db +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" From 33ce083b0dea50cd9590267463eeb4013202fc84 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 5 May 2019 07:05:05 +0200 Subject: [PATCH 4/4] doc/lint --- docs/database.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/database.rst b/docs/database.rst index 067017829..ce745e5cd 100644 --- a/docs/database.rst +++ b/docs/database.rst @@ -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