molecule-core/scripts/ops/test_check_migration_collisions.py
Hongming Wang b5df2126b9 fix(test): convert migration-collision tests from pytest to unittest (#2341)
CI failure: the Ops scripts (unittest) job runs `python -m unittest
discover` which doesn't have pytest installed. test_check_migration_
collisions.py imported pytest unconditionally, failing module import:

  ImportError: Failed to import test module: test_check_migration_collisions
  Traceback (most recent call last):
    File ".../test_check_migration_collisions.py", line 12, in <module>
      import pytest
  ModuleNotFoundError: No module named 'pytest'

The tests use no pytest-specific features (just bare assert + plain
class). Sibling test_sweep_cf_decide.py in the same dir already uses
unittest.TestCase. Convert this one to match: drop the pytest import,
make TestMigrationFileRe inherit from unittest.TestCase.

unittest.TestLoader.discover() requires TestCase subclasses for
auto-discovery, so the fix is two lines (drop import, add base).
Bare assert statements work fine inside TestCase methods.

Verified: `python3 -m unittest scripts.ops.test_check_migration_collisions -v`
runs all 9 tests, all pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 01:47:27 -07:00

66 lines
2.6 KiB
Python

"""Unit tests for check_migration_collisions.py — focuses on the regex
classifier + the diff/base-set logic that runs without git.
The end-to-end git diff + gh pr list path is exercised manually (running
the workflow against test PRs). These tests pin the pure-logic surface
so a regression in migration-name parsing fails immediately at PR time.
Run locally: ``python3 -m unittest scripts/ops/test_check_migration_collisions.py -v``
"""
import importlib.util
import unittest
from pathlib import Path
# Load the script as a module without invoking main(). We import the
# regex + helpers directly so we can test them without setting up git.
SCRIPT_PATH = Path(__file__).parent / "check_migration_collisions.py"
spec = importlib.util.spec_from_file_location("ccm", SCRIPT_PATH)
ccm = importlib.util.module_from_spec(spec)
spec.loader.exec_module(ccm)
class TestMigrationFileRe(unittest.TestCase):
"""The regex classifier — the load-bearing piece of the detector."""
def test_matches_standard_three_digit_prefix(self):
m = ccm.MIGRATION_FILE_RE.match("044_platform_inbound_secret.up.sql")
assert m is not None
assert int(m.group(1)) == 44
assert m.group(2) == "up"
def test_matches_down_migration(self):
m = ccm.MIGRATION_FILE_RE.match("044_platform_inbound_secret.down.sql")
assert m is not None
assert int(m.group(1)) == 44
assert m.group(2) == "down"
def test_matches_date_shaped_prefix(self):
# Real example from the repo: 20260417000000_workflow_checkpoints
m = ccm.MIGRATION_FILE_RE.match("20260417000000_workflow_checkpoints.up.sql")
assert m is not None
assert int(m.group(1)) == 20260417000000
def test_matches_long_compound_name(self):
m = ccm.MIGRATION_FILE_RE.match("042_a2a_queue.up.sql")
assert m is not None
assert int(m.group(1)) == 42
def test_rejects_no_prefix(self):
assert ccm.MIGRATION_FILE_RE.match("readme.md") is None
def test_rejects_alpha_prefix(self):
assert ccm.MIGRATION_FILE_RE.match("abc_migration.up.sql") is None
def test_rejects_wrong_extension(self):
assert ccm.MIGRATION_FILE_RE.match("044_test.sql") is None
assert ccm.MIGRATION_FILE_RE.match("044_test.up.txt") is None
def test_rejects_path_separator(self):
# Filename only — paths come pre-split via Path(line).name
assert ccm.MIGRATION_FILE_RE.match("044/test.up.sql") is None
def test_rejects_no_underscore(self):
# Naming convention requires <digits>_<name>
assert ccm.MIGRATION_FILE_RE.match("044.up.sql") is None