Django-testing-utils
Django-Testing-Utils is a package providing test helpers for django app testing.
Installation
pip install django-testing-utils
Usage
TestCase metaclass
Django 3.2 introduces setUpTestData attributes isolation, but django-testing-utils has slightly different way of resetting class attributes between tests. It collects all django model objects created in any TestCase class method and runs refresh_from_db() when necessary. It also clears fields_cache for such objects.
from django_testing_utils import mixins
from testproject.testapp import models
class SomeTestCase(mixins.BaseTestCase):
""" Some test case that uses django models."""
@classmethod
def setUpTestData(cls):
super().setUpTestData()
# In large code django docs recommend to create common objects in
# this method to speedup tests setup by reusing objects in db.
cls.project = models.Project.objects.create(name='project')
def test_something(self):
# in this test self.project instance is independent from other tests
...
Time mocking
There are multiple ways to freeze time in tests:
- ad-hoc mocking with
unittest.mock - freezegun library
- any system approach that puts working with time in order
django-testing-utils provides a way to use last approach in test with some limitations:
- Project code must work with
django.utils.timezonemethods only - All tests should inherit
TimeMixinfrom django-testing-utils
This leads to a systematic way of datetime and timezone usage in the project and it's tests.
from django.test import TestCase
from django_testing_utils.mixins import TimeMixin, second
class MyTimeTestCase(TimeMixin, TestCase):
@classmethod
def setUpTestData(cls):
# time is not mocked here yet
...
def setUp(self) -> None:
# not yet...
super().setUp()
# ... and here time has been frozen to `self.now`
def test_something(self):
# simulate time run
self.now += second
Helpers for django objects
There are some helper methods to work with django objects
update_object- performs anUPDATEon django model in a database. This does not affect field values for an object passed to this method.reload- fetches a new model instance from a database via primary key.assert_object_fieldsfetches an actual version from a database and compares all fields with values passed as named arguments
from django_testing_utils.mixins import BaseTestCase
from testapp import models
class MyTimeTestCase(BaseTestCase):
def test_something(self):
obj = models.Project.objects.create()
# change something in db
self.update_object(obj, name='new')
# fetch updated version
new = self.reload(obj)
# old object is untouched
self.assertNotEqual(new.name, obj.name)
# you could fetch and object and compare some fields in a single call
self.assert_object_fields(obj, name='new')
Decorators
-
override_defaults- a test case/test method decorator to change default values that are stored inapp.defaultsmodule. The idea ofapp.defaultsis to reduce a number of rarely changed variables in django settings module by moving it to application-specific settings -
disable_patcher- a context manager / decorator to temporarily disable someunittest.patchinstances defined in TestCase instance. This breaks open/close principle but allows postponing tests refactoring when some mocks are too generic.
from django.test import TestCase
from django.utils import timezone
from django_testing_utils.mixins import TimeMixin
from django_testing_utils.utils import override_defaults, disable_patchers
from testapp import defaults
import testapp
class MyTestCase(TimeMixin, TestCase):
@override_defaults(testapp.__name__, setting_1=42)
def test_setting_value(self):
self.assertEqual(defaults.setting_1, 42)
@disable_patchers('now_patcher')
def test_real_time(self):
# now patcher from TimeMixin is now disabled
with disable_patchers(self.timezone_datetime_patcher):
# timezone.datetime patcher is not also disabled
self.assertNotEqual(timezone.now(), timezone.now())
Metadata
Release files for django-testing-utils 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_testing_utils-0.8.0.tar.gz | 9.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_testing_utils-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.6 kB
Release files / django_testing_utils-0.8.0.tar.gz
| Download URL | django_testing_utils-0.8.0.tar.gz |
|---|---|
| Size | 9.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8a7df7d17dd8562617592c4233405c80e90b994ee74bba2a963c45ca2707a32d
|
|
BLAKE2b-256 checksum How to use checksums |
c79a0eac568ea49b5ff9a65736afd541ddd56d1f5818c88492e0284ee671cf02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / django_testing_utils-0.8.0-py3-none-any.whl
| Download URL | django_testing_utils-0.8.0-py3-none-any.whl |
|---|---|
| Size | 8.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
144706a5b6af1fda5d6011568bb54b5709d4d75857afe5b9e299ac69d8a2769b
|
|
BLAKE2b-256 checksum How to use checksums |
3985363e79d5f9e8f9717049395db0b7ad59ee50035b0649c0788a227a8cb197
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|