Files
odysseus/tests/test_taxonomy.py
2026-06-09 01:13:28 +02:00

146 lines
4.8 KiB
Python

"""Unit tests for tests/_taxonomy.py - the test-taxonomy classification module.
These tests pin the conservative classification behavior directly, without
running pytest collection. They import only the module under test (a test-support
module, not production code) and touch no filesystem.
"""
import re
import pytest
from tests._taxonomy import (
classify_test_path,
discover_markers,
markers_for_path,
normalize_marker_name,
)
# --- normalize_marker_name ---------------------------------------------------
def test_normalize_lowercases():
assert normalize_marker_name("Area_Security") == "area_security"
def test_normalize_converts_nonalphanumeric_runs_to_underscore():
assert normalize_marker_name("owner--scope..test") == "owner_scope_test"
def test_normalize_strips_leading_and_trailing_underscores():
assert normalize_marker_name("__owner-scope__") == "owner_scope"
# --- classify_test_path: one example per area --------------------------------
@pytest.mark.parametrize("filename, expected_area, expected_sub", [
("test_owner_scope.py", "security", "owner_scope"),
("test_cookbook_helpers.py", "services", "cookbook"),
("test_routes_sessions.py", "routes", "routes"),
("test_backup_cli.py", "cli", "cli"),
("test_compare_js.py", "js", "js"),
("segmenter.test.mjs", "js", "js"),
("segmenter.test.js", "js", "js"),
("segmenter.test.ts", "js", "js"),
("test_helpers_import_state.py", "helpers", "helpers"),
("test_atomic_io.py", "unit", "atomic"),
])
def test_classify_examples(filename, expected_area, expected_sub):
result = classify_test_path(filename)
assert result.area == expected_area
assert result.sub_area == expected_sub
# --- classify_test_path: fallback --------------------------------------------
def test_unknown_filename_is_uncategorized():
result = classify_test_path("test_widget_gizmo_thing.py")
assert result.area == "uncategorized"
def test_uncategorized_sub_area_is_derived_from_filename_tokens():
result = classify_test_path("test_archived_sessions_model_filter.py")
assert result.area == "uncategorized"
assert result.sub_area == "archived_sessions_model_filter"
# --- markers_for_path --------------------------------------------------------
def test_markers_for_path_returns_one_area_and_one_sub():
markers = markers_for_path("test_owner_scope.py")
assert markers == ("area_security", "sub_owner_scope")
assert len([m for m in markers if m.startswith("area_")]) == 1
assert len([m for m in markers if m.startswith("sub_")]) == 1
def test_markers_for_path_are_normalized():
markers = markers_for_path("test_foo-bar.py")
assert markers == ("area_uncategorized", "sub_foo_bar")
for marker in markers:
assert re.fullmatch(r"[a-z0-9_]+", marker)
# --- discover_markers --------------------------------------------------------
def test_discover_markers_is_sorted_and_deduplicated():
paths = [
"test_owner_scope.py",
"test_owner_scope.py",
"test_cookbook_helpers.py",
]
markers = discover_markers(paths)
assert markers == tuple(sorted(set(markers)))
assert markers == (
"area_security",
"area_services",
"sub_cookbook",
"sub_owner_scope",
)
def test_discover_markers_includes_area_and_sub():
markers = discover_markers(["test_owner_scope.py"])
assert any(m.startswith("area_") for m in markers)
assert any(m.startswith("sub_") for m in markers)
# --- edge cases --------------------------------------------------------------
def test_normalize_all_symbols_becomes_empty():
assert normalize_marker_name("@@@") == ""
def test_bare_test_filename_is_fully_uncategorized():
result = classify_test_path("tests/test.py")
assert result.area == "uncategorized"
assert result.sub_area == "uncategorized"
def test_markers_for_bare_test_filename():
markers = markers_for_path("tests/test.py")
assert "area_uncategorized" in markers
assert "sub_uncategorized" in markers
@pytest.mark.parametrize("path", [
"tests/helpers/test_module_isolation.py",
"/work/repo/tests/helpers/test_module_isolation.py",
])
def test_file_under_helpers_dir_is_helpers(path):
result = classify_test_path(path)
assert result.area == "helpers"
assert result.sub_area == "helpers"
# --- priority contract -------------------------------------------------------
def test_security_beats_services_when_both_tokens_present():
result = classify_test_path("test_email_owner_scope.py")
assert result.area == "security"
assert result.sub_area == "owner_scope"
def test_unrelated_helpers_ancestor_is_not_helpers():
result = classify_test_path("/work/helpers/odysseus/tests/test_owner_scope.py")
assert result.area == "security"
assert result.sub_area == "owner_scope"