Files
roboco/tests/integration/test_migration_observability.py
T

49 lines
1.7 KiB
Python
Raw Normal View History

2026-06-23 07:26:41 +02:00
"""0.10.0 observability: tasks.revision_count + the audit_log query index.
Migration 045 adds ``tasks.revision_count`` (the O(1) rework counter —
forward-only, existing rows default to 0) and the composite index
``audit_log(target_id, event_type, timestamp)`` that powers the cycle-time and
rework reconstruction queries. The real upgrade/downgrade chain is verified
separately against a throwaway Postgres (see project migration-verification
discipline); these assertions guard the resulting schema shape.
"""
from __future__ import annotations
2026-06-29 05:38:21 +02:00
from typing import TYPE_CHECKING
2026-06-23 07:26:41 +02:00
import pytest
from sqlalchemy import text
2026-06-29 05:38:21 +02:00
if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
2026-06-23 07:26:41 +02:00
@pytest.mark.asyncio
2026-06-29 05:38:21 +02:00
async def test_revision_count_defaults_to_zero(db_session: AsyncSession) -> None:
2026-06-23 07:26:41 +02:00
result = await db_session.execute(
text(
"SELECT column_default, is_nullable "
"FROM information_schema.columns "
"WHERE table_name = 'tasks' AND column_name = 'revision_count'"
)
)
row = result.first()
assert row is not None, "tasks.revision_count column must exist"
assert row[1] == "NO", "revision_count must be NOT NULL"
assert "0" in (row[0] or ""), "revision_count must default to 0"
@pytest.mark.asyncio
2026-06-29 05:38:21 +02:00
async def test_audit_log_query_index_exists(db_session: AsyncSession) -> None:
2026-06-23 07:26:41 +02:00
result = await db_session.execute(
text(
"SELECT indexname FROM pg_indexes "
"WHERE tablename = 'audit_log' "
"AND indexname = 'ix_audit_log_target_event_ts'"
)
)
assert result.first() is not None, (
"composite index ix_audit_log_target_event_ts must exist on audit_log"
)