summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Adams <christopher.r.adams@gmail.com>2022-06-25 17:15:55 -0400
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-06-27 20:53:06 +0200
commitaed1a73e0a848c5368abe57a6b57119acfdbbd67 (patch)
tree0011b85e8c2ab03f46c751a244be337976688ac7
parent6c0ee6179796aa67a2403d85f2759bd4d45c93bc (diff)
[4.1.x] Fixed #33422 -- Improved docs about isolating apps.
Backport of 90d2f9f41671ef01c8e8e7b5648f95c9bf512aae from main
-rw-r--r--docs/internals/contributing/writing-code/unit-tests.txt63
-rw-r--r--docs/topics/testing/tools.txt63
2 files changed, 65 insertions, 61 deletions
diff --git a/docs/internals/contributing/writing-code/unit-tests.txt b/docs/internals/contributing/writing-code/unit-tests.txt
index 62a3e31462..6b1c735ba4 100644
--- a/docs/internals/contributing/writing-code/unit-tests.txt
+++ b/docs/internals/contributing/writing-code/unit-tests.txt
@@ -522,25 +522,8 @@ Isolating model registration
To avoid polluting the global :attr:`~django.apps.apps` registry and prevent
unnecessary table creation, models defined in a test method should be bound to
-a temporary ``Apps`` instance::
-
- from django.apps.registry import Apps
- from django.db import models
- from django.test import SimpleTestCase
-
- class TestModelDefinition(SimpleTestCase):
- def test_model_definition(self):
- test_apps = Apps(['app_label'])
-
- class TestModel(models.Model):
- class Meta:
- apps = test_apps
- ...
-
-.. function:: django.test.utils.isolate_apps(*app_labels, attr_name=None, kwarg_name=None)
-
-Since this pattern involves a lot of boilerplate, Django provides the
-:func:`~django.test.utils.isolate_apps` decorator. It's used like this::
+a temporary ``Apps`` instance. To do this, use the
+:func:`~django.test.utils.isolate_apps` decorator::
from django.db import models
from django.test import SimpleTestCase
@@ -581,45 +564,3 @@ Since this pattern involves a lot of boilerplate, Django provides the
class Meta:
app_label = 'other_app_label'
...
-
-The decorator can also be applied to classes::
-
- from django.db import models
- from django.test import SimpleTestCase
- from django.test.utils import isolate_apps
-
- @isolate_apps('app_label')
- class TestModelDefinition(SimpleTestCase):
- def test_model_definition(self):
- class TestModel(models.Model):
- pass
- ...
-
-The temporary ``Apps`` instance used to isolate model registration can be
-retrieved as an attribute when used as a class decorator by using the
-``attr_name`` parameter::
-
- from django.db import models
- from django.test import SimpleTestCase
- from django.test.utils import isolate_apps
-
- @isolate_apps('app_label', attr_name='apps')
- class TestModelDefinition(SimpleTestCase):
- def test_model_definition(self):
- class TestModel(models.Model):
- pass
- self.assertIs(self.apps.get_model('app_label', 'TestModel'), TestModel)
-
-Or as an argument on the test method when used as a method decorator by using
-the ``kwarg_name`` parameter::
-
- from django.db import models
- from django.test import SimpleTestCase
- from django.test.utils import isolate_apps
-
- class TestModelDefinition(SimpleTestCase):
- @isolate_apps('app_label', kwarg_name='apps')
- def test_model_definition(self, apps):
- class TestModel(models.Model):
- pass
- self.assertIs(apps.get_model('app_label', 'TestModel'), TestModel)
diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt
index dcbfefd295..90da7d91c7 100644
--- a/docs/topics/testing/tools.txt
+++ b/docs/topics/testing/tools.txt
@@ -1403,6 +1403,69 @@ LOCALE_PATHS, LANGUAGE_CODE Default translation and loaded translations
MEDIA_ROOT, DEFAULT_FILE_STORAGE Default file storage
================================ ========================
+Isolating apps
+--------------
+
+.. function:: utils.isolate_apps(*app_labels, attr_name=None, kwarg_name=None)
+
+ Registers the models defined within a wrapped context into their own
+ isolated :attr:`~django.apps.apps` registry. This functionality is useful
+ when creating model classes for tests, as the classes will be cleanly
+ deleted afterward, and there is no risk of name collisions.
+
+ The app labels which the isolated registry should contain must be passed as
+ individual arguments. You can use ``isolate_apps()`` as a decorator or a
+ context manager. For example::
+
+ from django.db import models
+ from django.test import SimpleTestCase
+ from django.test.utils import isolate_apps
+
+ class MyModelTests(SimpleTestCase):
+
+ @isolate_apps("app_label")
+ def test_model_definition(self):
+ class TestModel(models.Model):
+ pass
+ ...
+
+ … or::
+
+ with isolate_apps("app_label"):
+ class TestModel(models.Model):
+ pass
+ ...
+
+ The decorator form can also be applied to classes.
+
+ Two optional keyword arguments can be specified:
+
+ * ``attr_name``: attribute assigned the isolated registry if used as a
+ class decorator.
+ * ``kwarg_name``: keyword argument passing the isolated registry if used as
+ a function decorator.
+
+ The temporary ``Apps`` instance used to isolate model registration can be
+ retrieved as an attribute when used as a class decorator by using the
+ ``attr_name`` parameter::
+
+ @isolate_apps("app_label", attr_name="apps")
+ class TestModelDefinition(SimpleTestCase):
+ def test_model_definition(self):
+ class TestModel(models.Model):
+ pass
+ self.assertIs(self.apps.get_model("app_label", "TestModel"), TestModel)
+
+ … or alternatively as an argument on the test method when used as a method
+ decorator by using the ``kwarg_name`` parameter::
+
+ class TestModelDefinition(SimpleTestCase):
+ @isolate_apps("app_label", kwarg_name="apps")
+ def test_model_definition(self, apps):
+ class TestModel(models.Model):
+ pass
+ self.assertIs(apps.get_model("app_label", "TestModel"), TestModel)
+
.. _emptying-test-outbox:
Emptying the test outbox