Let CI also check for missing migrations (#706)

* Refactor: re-arrange test application

This was triggered by the need to run "python manage.py", which is impossible when serving the whole project in the same directory as is configured in INSTALLED_APPS ("auditlog_tests"). This setup is heavily inspired by other jazzband projects.

* Add check for missing migrations
This commit is contained in:
sebastianmanger 2025-03-19 17:28:43 +01:00 committed by GitHub
parent 4c1d573981
commit 6414b7aedb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 55 additions and 59 deletions

View file

@ -384,7 +384,9 @@ class LogEntry(models.Model):
additional_data = models.JSONField(
blank=True, null=True, verbose_name=_("additional data")
)
actor_email = models.CharField(blank=True, null=True, max_length=254)
actor_email = models.CharField(
blank=True, null=True, max_length=254, verbose_name=_("actor email")
)
objects = LogEntryManager()

View file

@ -3,7 +3,7 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "auditlog_tests.test_settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_settings")
from django.core.management import execute_from_command_line

View file

@ -2,4 +2,4 @@ from django.apps import AppConfig
class AuditlogTestConfig(AppConfig):
name = "auditlog_tests"
name = "test_app"

View file

@ -1,6 +1,6 @@
[
{
"model": "auditlog_tests.manyrelatedmodel",
"model": "test_app.manyrelatedmodel",
"pk": 1,
"fields": {
"recursive": [1],
@ -8,7 +8,7 @@
}
},
{
"model": "auditlog_tests.manyrelatedothermodel",
"model": "test_app.manyrelatedothermodel",
"pk": 1,
"fields": {}
}

View file

@ -1,13 +1,13 @@
from django.contrib import admin
from django.urls import path
from auditlog_tests.views import SimpleModelDetailview
from .views import SimpleModelDetailView
urlpatterns = [
path("admin/", admin.site.urls),
path(
"simplemodel/<int:pk>/",
SimpleModelDetailview.as_view(),
SimpleModelDetailView.as_view(),
name="simplemodel-detail",
),
]

View file

@ -1,9 +1,10 @@
from django.views.generic import DetailView
from auditlog.mixins import LogAccessMixin
from auditlog_tests.models import SimpleModel
from .models import SimpleModel
class SimpleModelDetailview(LogAccessMixin, DetailView):
class SimpleModelDetailView(LogAccessMixin, DetailView):
model = SimpleModel
template_name = "simplemodel_detail.html"

View file

@ -7,8 +7,7 @@ from unittest import mock
import freezegun
from django.core.management import call_command
from django.test import TestCase, TransactionTestCase
from auditlog_tests.models import SimpleModel
from test_app.models import SimpleModel
class AuditlogFlushTest(TestCase):

View file

@ -16,7 +16,7 @@ INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.staticfiles",
"auditlog",
"auditlog_tests",
"test_app",
]
MIDDLEWARE = [
@ -57,7 +57,7 @@ TEMPLATES = [
STATIC_URL = "/static/"
ROOT_URLCONF = "auditlog_tests.urls"
ROOT_URLCONF = "test_app.urls"
USE_TZ = True

View file

@ -4,9 +4,9 @@ from unittest.mock import patch
from django.core.management import CommandError, call_command
from django.test import TestCase, override_settings
from test_app.models import SimpleModel
from auditlog.models import LogEntry
from auditlog_tests.models import SimpleModel
class TwoStepMigrationTest(TestCase):

View file

@ -26,17 +26,8 @@ from django.utils import dateformat, formats
from django.utils import timezone as django_timezone
from django.utils.encoding import smart_str
from django.utils.translation import gettext_lazy as _
from auditlog.admin import LogEntryAdmin
from auditlog.cid import get_cid
from auditlog.context import disable_auditlog, set_actor
from auditlog.diff import model_instance_diff
from auditlog.middleware import AuditlogMiddleware
from auditlog.models import DEFAULT_OBJECT_REPR, LogEntry
from auditlog.registry import AuditlogModelRegistry, AuditLogRegistrationError, auditlog
from auditlog.signals import post_log, pre_log
from auditlog_tests.fixtures.custom_get_cid import get_cid as custom_get_cid
from auditlog_tests.models import (
from test_app.fixtures.custom_get_cid import get_cid as custom_get_cid
from test_app.models import (
AdditionalDataIncludedModel,
AltPrimaryKeyModel,
AutoManyRelatedModel,
@ -68,6 +59,15 @@ from auditlog_tests.models import (
UUIDPrimaryKeyModel,
)
from auditlog.admin import LogEntryAdmin
from auditlog.cid import get_cid
from auditlog.context import disable_auditlog, set_actor
from auditlog.diff import model_instance_diff
from auditlog.middleware import AuditlogMiddleware
from auditlog.models import DEFAULT_OBJECT_REPR, LogEntry
from auditlog.registry import AuditlogModelRegistry, AuditLogRegistrationError, auditlog
from auditlog.signals import post_log, pre_log
class SimpleModelTest(TestCase):
def setUp(self):
@ -631,9 +631,7 @@ class MiddlewareTest(TestCase):
# these two tuples test using a custom getter.
# Here, we don't necessarily care about the cid that was set in set_cid
(
{
"AUDITLOG_CID_GETTER": "auditlog_tests.fixtures.custom_get_cid.get_cid"
},
{"AUDITLOG_CID_GETTER": "test_app.fixtures.custom_get_cid.get_cid"},
custom_get_cid(),
),
({"AUDITLOG_CID_GETTER": custom_get_cid}, custom_get_cid()),
@ -1254,15 +1252,12 @@ class RegisterModelSettingsTest(TestCase):
# Exclude just one model
self.assertTrue(
SimpleExcludeModel
in self.test_auditlog._get_exclude_models(
("auditlog_tests.SimpleExcludeModel",)
)
in self.test_auditlog._get_exclude_models(("test_app.SimpleExcludeModel",))
)
# Exclude all model of an app
self.assertTrue(
SimpleExcludeModel
in self.test_auditlog._get_exclude_models(("auditlog_tests",))
SimpleExcludeModel in self.test_auditlog._get_exclude_models(("test_app",))
)
def test_register_models_no_models(self):
@ -1271,13 +1266,13 @@ class RegisterModelSettingsTest(TestCase):
self.assertEqual(self.test_auditlog._registry, {})
def test_register_models_register_single_model(self):
self.test_auditlog._register_models(("auditlog_tests.SimpleExcludeModel",))
self.test_auditlog._register_models(("test_app.SimpleExcludeModel",))
self.assertTrue(self.test_auditlog.contains(SimpleExcludeModel))
self.assertEqual(len(self.test_auditlog._registry), 1)
def test_register_models_register_app(self):
self.test_auditlog._register_models(("auditlog_tests",))
self.test_auditlog._register_models(("test_app",))
self.assertTrue(self.test_auditlog.contains(SimpleExcludeModel))
self.assertTrue(self.test_auditlog.contains(ChoicesFieldModel))
@ -1287,7 +1282,7 @@ class RegisterModelSettingsTest(TestCase):
self.test_auditlog._register_models(
(
{
"model": "auditlog_tests.SimpleExcludeModel",
"model": "test_app.SimpleExcludeModel",
"include_fields": ["label"],
"exclude_fields": [
"text",
@ -1305,7 +1300,7 @@ class RegisterModelSettingsTest(TestCase):
self.test_auditlog._register_models(
(
{
"model": "auditlog_tests.ManyRelatedModel",
"model": "test_app.ManyRelatedModel",
"m2m_fields": {"related"},
},
)
@ -1427,7 +1422,7 @@ class RegisterModelSettingsTest(TestCase):
@override_settings(
AUDITLOG_INCLUDE_ALL_MODELS=True,
AUDITLOG_EXCLUDE_TRACKING_MODELS=("auditlog_tests.SimpleExcludeModel",),
AUDITLOG_EXCLUDE_TRACKING_MODELS=("test_app.SimpleExcludeModel",),
)
def test_register_from_settings_register_all_models_with_exclude_models_tuple(self):
self.test_auditlog.register_from_settings()
@ -1473,7 +1468,7 @@ class RegisterModelSettingsTest(TestCase):
@override_settings(
AUDITLOG_INCLUDE_ALL_MODELS=True,
AUDITLOG_EXCLUDE_TRACKING_MODELS=["auditlog_tests.SimpleExcludeModel"],
AUDITLOG_EXCLUDE_TRACKING_MODELS=["test_app.SimpleExcludeModel"],
)
def test_register_from_settings_register_all_models_with_exclude_models_list(self):
self.test_auditlog.register_from_settings()
@ -1484,7 +1479,7 @@ class RegisterModelSettingsTest(TestCase):
@override_settings(
AUDITLOG_INCLUDE_TRACKING_MODELS=(
{
"model": "auditlog_tests.SimpleExcludeModel",
"model": "test_app.SimpleExcludeModel",
"include_fields": ["label"],
"exclude_fields": [
"text",
@ -2818,7 +2813,9 @@ class DisableTest(TestCase):
This only works with context manager
"""
with disable_auditlog():
management.call_command("loaddata", "m2m_test_fixture.json", verbosity=0)
management.call_command(
"loaddata", "test_app/fixtures/m2m_test_fixture.json", verbosity=0
)
recursive = ManyRelatedModel.objects.get(pk=1)
self.assertEqual(0, LogEntry.objects.get_for_object(recursive).count())
related = ManyRelatedOtherModel.objects.get(pk=1)

View file

@ -19,10 +19,11 @@ from auditlog import __version__
# documentation root, use os.path.abspath to make it absolute, like shown here.
# Add sources folder
sys.path.insert(0, os.path.abspath("../../"))
sys.path.insert(0, os.path.abspath("../../auditlog_tests"))
# Setup Django for autodoc
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "auditlog_tests.test_settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_settings")
import django # noqa: E402
django.setup()

View file

@ -1,15 +0,0 @@
#!/usr/bin/env python
import os
import sys
import django
from django.conf import settings
from django.test.utils import get_runner
if __name__ == "__main__":
os.environ["DJANGO_SETTINGS_MODULE"] = "auditlog_tests.test_settings"
django.setup()
TestRunner = get_runner(settings)
test_runner = TestRunner()
failures = test_runner.run_tests(["auditlog_tests"])
sys.exit(bool(failures))

13
tox.ini
View file

@ -6,12 +6,14 @@ envlist =
{py312,py313}-djangomain
py39-docs
py39-lint
py39-checkmigrations
[testenv]
setenv =
COVERAGE_FILE={toxworkdir}/.coverage.{envname}
changedir = auditlog_tests
commands =
coverage run --source auditlog runtests.py
coverage run --source auditlog ./manage.py test
coverage xml
deps =
django42: Django>=4.2,<4.3
@ -47,6 +49,15 @@ deps = pre-commit
commands =
pre-commit run --all-files
[testenv:py39-checkmigrations]
description = Check for missing migrations
changedir = auditlog_tests
deps =
Django>=4.2
psycopg2
commands =
python manage.py makemigrations --check --dry-run
[gh-actions]
python =
3.9: py39