Skip to content

Commit ce52a64

Browse files
committed
Add tests for the names of migration files
1 parent ac88765 commit ce52a64

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

tests/migration/test_migration.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from __future__ import annotations
22

33
import contextlib
4+
import os
45
import pathlib
6+
import subprocess
57
import warnings
68

9+
import packaging.version
710
import pytest
811
from django.core import management
912
from django.db import connection
@@ -98,3 +101,93 @@ def test_django_migrations_run_properly(django_db):
98101

99102
def test_no_missing_django_migration(django_db):
100103
management.call_command("makemigrations", "procrastinate", dry_run=True, check=True)
104+
105+
106+
@pytest.fixture(scope="module")
107+
def latest_version() -> packaging.version.Version:
108+
if latest_tag := os.environ.get("LATEST_TAG"):
109+
return packaging.version.Version(latest_tag)
110+
111+
if "CI" in os.environ:
112+
raise ValueError("Cannot fetch latest tag in CI unless LATEST_TAG is set")
113+
114+
# If we're not in the CI, we can accept loosing a bit of time to fetch the latest tag
115+
try:
116+
subprocess.check_call(["git", "fetch", "--tags"])
117+
out = subprocess.check_output(["git", "tag", "--list"], text=True)
118+
except subprocess.CalledProcessError as exc:
119+
raise ValueError("Cannot fetch latest tag") from exc
120+
121+
return max(packaging.version.Version(tag) for tag in out.splitlines())
122+
123+
124+
migration_files = sorted(
125+
(pathlib.Path(__file__).parents[2] / "procrastinate" / "sql" / "migrations").glob(
126+
"*.sql"
127+
)
128+
)
129+
130+
131+
@pytest.fixture(scope="module")
132+
def new_migrations(latest_version) -> set[pathlib.Path]:
133+
# git diff latest_version..HEAD --name-only --diff-filter=A
134+
135+
try:
136+
out = subprocess.check_output(
137+
[
138+
"git",
139+
"diff",
140+
f"{latest_version}..HEAD",
141+
"--name-only",
142+
"--diff-filter=A",
143+
],
144+
text=True,
145+
)
146+
except subprocess.CalledProcessError as exc:
147+
raise ValueError("Cannot fetch new migrations") from exc
148+
149+
return {pathlib.Path(path) for path in out.splitlines()}
150+
151+
152+
@pytest.mark.parametrize(
153+
"migration", [pytest.param(m, id=m.name) for m in migration_files]
154+
)
155+
def test_migration_properly_named(
156+
migration: pathlib.Path,
157+
latest_version: packaging.version.Version,
158+
new_migrations: set[pathlib.Path],
159+
):
160+
# migration is:
161+
# pathlib.Path("..." / "03.00.00_01_pre_cancel_notification.sql")
162+
163+
migration_name_parts = migration.stem.split("_", 3)
164+
version_str, index_str, *pre_post_name = migration_name_parts
165+
166+
mig_version = packaging.version.Version(version_str)
167+
168+
next_minor = packaging.version.Version(
169+
f"{latest_version.major}.{latest_version.minor + 1}.0"
170+
)
171+
172+
if migration in new_migrations:
173+
assert mig_version == next_minor
174+
else:
175+
assert mig_version <= latest_version
176+
177+
if mig_version < packaging.version.Version("3.0.0"):
178+
pre_post = "pre"
179+
name = pre_post_name[0]
180+
else:
181+
pre_post, name = pre_post_name
182+
183+
index = int(index_str)
184+
if pre_post == "pre":
185+
assert 1 <= index < 50
186+
elif pre_post == "post":
187+
assert 50 <= index
188+
else:
189+
assert False, f"Invalid migration name: expecting 'pre' or 'post': {pre_post}"
190+
191+
assert name == name.lower()
192+
assert "-" not in name
193+
assert " " not in name

0 commit comments

Comments
 (0)