Option C Tools
Loading...
Searching...
No Matches
test_test_file_index.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_linter/test_test_file_index.py
4
5"""
6Purpose
7-------
8OI-510 / FS-516 regression coverage — :func:`build_test_index` must
9walk ``tests_dir`` exactly once per linter run and produce two lookup
10sets on :class:`LinterContext`. :func:`check_tests_exist` then becomes
11O(1) per call, replacing the previous O(N·M) rglob-and-read loop that
12dominated ``oct lint`` runtime on medium-to-large projects.
13
14Responsibilities
15----------------
16- Verify first call builds and caches ``ctx.test_index``; subsequent
17 calls return the cached dict without re-walking.
18- Verify both naming-convention and import-statement paths populate the
19 index.
20- Verify ``check_tests_exist`` returns True for either lookup path.
21
22Diagnostics
23-----------
24Domain: LINTER-TESTS
25Levels:
26 L2 — test lifecycle
27 L3 — assertion details
28 L4 — deep tracing
29
30Contracts
31---------
32- First call builds and caches ``ctx.test_index``; subsequent calls
33 return the cached dict without re-walking.
34- Both naming-convention and import-statement paths populate the index.
35- ``check_tests_exist`` returns True for either path.
36"""
37
38from __future__ import annotations
39
40import threading
41from pathlib import Path
42
43from oct.linter.oct_lint import (
44 LinterContext,
45 build_test_index,
46 check_tests_exist,
47)
48
49
50def _make_ctx(project: Path) -> LinterContext:
51 return LinterContext(
52 project_root=project,
53 project_name="demo",
54 diagnostics_dir=project / "oc_diagnostics",
55 tests_dir=project / "tests",
56 docs_dir=project / "docs",
57 log_lock=threading.Lock(),
58 )
59
60
62 """OI-510: name-matched and import-matched stems both land in the index."""
63 (tmp_path / "tests").mkdir()
64 (tmp_path / "tests" / "test_foo.py").write_text("assert True\n", encoding="utf-8")
65 (tmp_path / "tests" / "test_explicit.py").write_text(
66 "from bar import baz\nimport qux\n", encoding="utf-8",
67 )
68 ctx = _make_ctx(tmp_path)
69 index = build_test_index(ctx)
70 assert "foo" in index["name_stems"]
71 assert "explicit" in index["name_stems"]
72 assert "bar" in index["imported_stems"]
73 assert "qux" in index["imported_stems"]
74
75
76def test_index_is_cached(tmp_path: Path):
77 """OI-510: the index is built on first call and reused thereafter."""
78 (tmp_path / "tests").mkdir()
79 (tmp_path / "tests" / "test_a.py").write_text("\n", encoding="utf-8")
80 ctx = _make_ctx(tmp_path)
81 first = build_test_index(ctx)
82 # Mutating the disk after first call must not affect the cached result.
83 (tmp_path / "tests" / "test_b.py").write_text("\n", encoding="utf-8")
84 second = build_test_index(ctx)
85 assert first is second
86 assert "b" not in second["name_stems"]
87
88
90 """OI-510: check_tests_exist returns True via either path, False otherwise."""
91 (tmp_path / "tests").mkdir()
92 (tmp_path / "tests" / "test_named_hit.py").write_text("\n", encoding="utf-8")
93 (tmp_path / "tests" / "test_imports.py").write_text(
94 "import import_hit\n", encoding="utf-8",
95 )
96 ctx = _make_ctx(tmp_path)
97 assert check_tests_exist(Path("src/named_hit.py"), ctx) is True
98 assert check_tests_exist(Path("src/import_hit.py"), ctx) is True
99 assert check_tests_exist(Path("src/no_hit.py"), ctx) is False
100
101
103 """OI-510: absent tests/ folder → empty sets, no exception."""
104 ctx = _make_ctx(tmp_path) # no tests/ on disk
105 index = build_test_index(ctx)
106 assert index["name_stems"] == set()
107 assert index["imported_stems"] == set()
108 assert check_tests_exist(Path("anything.py"), ctx) is False
LinterContext _make_ctx(Path project)