Files
xiaobaifupan/app/tests/test_preservation_slice_ladder_rotation.py
T

94 lines
3.0 KiB
Python

from __future__ import annotations
import ast
import hashlib
import unittest
from pathlib import Path
from tests.preservation_helpers import (
assert_frontend_runtime_matches_audited_baseline,
assert_moved_asset_matches,
assert_page_prefix_matches,
)
APP_ROOT = Path(__file__).resolve().parents[1]
ORIGINAL_ROOT = APP_ROOT.parent
ROTATION_METHODS = {
"rotation_history",
"rotation_sector_members",
}
LADDER_ROTATION_BUILDERS = {
"_build_ladders",
"_build_sector_rotation",
}
def class_methods(path: Path, class_name: str) -> dict[str, str]:
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
owner = next(
node
for node in tree.body
if isinstance(node, ast.ClassDef) and node.name == class_name
)
return {
node.name: ast.dump(node, include_attributes=False)
for node in owner.body
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
}
def top_level_functions(path: Path) -> dict[str, str]:
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
return {
node.name: ast.dump(node, include_attributes=False)
for node in tree.body
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
and node.name in LADDER_ROTATION_BUILDERS
}
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
class LadderRotationSliceSourceEquivalenceTests(unittest.TestCase):
def test_rotation_service_methods_are_exact_original_ast(self) -> None:
original = class_methods(ORIGINAL_ROOT / "server.py", "DashboardService")
migrated = class_methods(
APP_ROOT / "backend" / "features" / "rotation" / "service.py",
"RotationServiceMixin",
)
self.assertEqual(set(migrated), ROTATION_METHODS)
for name in sorted(ROTATION_METHODS):
self.assertEqual(migrated[name], original[name], name)
def test_dashboard_service_no_longer_duplicates_rotation_methods(self) -> None:
remaining = class_methods(
APP_ROOT / "backend" / "application.py", "DashboardService"
)
self.assertTrue(ROTATION_METHODS.isdisjoint(remaining))
def test_ladder_and_rotation_builders_are_exact_original_ast(self) -> None:
self.assertEqual(
top_level_functions(ORIGINAL_ROOT / "tushare_client.py"),
top_level_functions(
APP_ROOT / "backend" / "data" / "providers" / "tushare_client.py"
),
)
def test_api_and_frontend_assets_are_unchanged(self) -> None:
self.assertEqual(
sha256(APP_ROOT / "config/api.config.json"),
sha256(ORIGINAL_ROOT / "config/api.config.json"),
)
assert_frontend_runtime_matches_audited_baseline(self)
assert_moved_asset_matches(self, "styles.css", "styles/styles.css")
for page in ("pages/ladder/page.js", "pages/rotation/page.js"):
assert_page_prefix_matches(self, page)
if __name__ == "__main__":
unittest.main()