Skip to content

Commit 4cfb590

Browse files
authored
Test the test coherence (#7318)
1 parent 9786bab commit 4cfb590

5 files changed

Lines changed: 72 additions & 7 deletions

File tree

.cursor/rules/test_the_test.mdc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
description: Rules for tests inside tests/test_the_test
3+
globs:
4+
alwaysApply: true
5+
---
6+
7+
# Which scenario contains tests/test_the_test functions and classes
8+
9+
All tests inside tests/test_the_test should belong to either TEST_THE_TEST, MOCK_THE_TEST or MOCK_THE_TEST_2. For almost all situation, they should belong to TEST_THE_TEST,

tests/test_the_test/test_itself.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""It's easy to forget to attach a test inside this folder to the right scenario"""
2+
3+
from utils import scenarios
4+
from .utils import get_scenario_map
5+
6+
7+
@scenarios.test_the_test
8+
def test_the_test_coherence():
9+
valid_scenarios = ("TEST_THE_TEST", "MOCK_THE_TEST", "MOCK_THE_TEST_2")
10+
scenario_map = get_scenario_map()
11+
12+
for node_id, scenario_list in scenario_map.items():
13+
if node_id.startswith("tests/test_the_test/"):
14+
for scenario in scenario_list:
15+
assert scenario in valid_scenarios, f"{node_id} should belong to TEST_THE_TEST"

tests/test_the_test/test_start_stop_agent.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from utils.docker_fixtures._test_agent import DEFAULT_OTLP_HTTP_PORT, DEFAULT_OTLP_GRPC_PORT
88

99

10+
@scenarios.test_the_test
1011
def test_start_agent_then_stop(request: pytest.FixtureRequest):
1112
# Docker-backed smoke test. Gate at runtime rather than with a module-level
1213
# pytest.mark.skipif: the root conftest's _item_must_pass iterates skipif

tests/test_the_test/test_test_agent_pool.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import contextlib
22
from collections.abc import Iterator
33

4+
from utils import scenarios
45
from utils.docker_fixtures._test_agent_pool import WorkerAgentPool, agent_env_key
56

67

@@ -36,10 +37,12 @@ def __call__(self, request: object, agent_env: dict[str, str]) -> Iterator[_Fake
3637
self.stopped += 1
3738

3839

40+
@scenarios.test_the_test
3941
def test_env_key_is_order_independent():
4042
assert agent_env_key({"A": "1", "B": "2"}) == agent_env_key({"B": "2", "A": "1"})
4143

4244

45+
@scenarios.test_the_test
4346
def test_same_env_reuses_and_clears():
4447
creator = _FakeCreator()
4548
with WorkerAgentPool(creator) as pool:
@@ -53,6 +56,7 @@ def test_same_env_reuses_and_clears():
5356
assert api1.rebind_calls == ["req2"] # rebound only on reuse, not on first acquire
5457

5558

59+
@scenarios.test_the_test
5660
def test_distinct_env_creates_separate_agents():
5761
creator = _FakeCreator()
5862
with WorkerAgentPool(creator) as pool:
@@ -63,6 +67,7 @@ def test_distinct_env_creates_separate_agents():
6367
assert len(creator.created_envs) == 2
6468

6569

70+
@scenarios.test_the_test
6671
def test_exit_tears_down_every_agent():
6772
creator = _FakeCreator()
6873
with WorkerAgentPool(creator) as pool:

tests/test_the_test/utils.py

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import json
22
import subprocess
3+
from pathlib import Path
34

45
from utils import logger
56

67

8+
def get_scenario_map() -> dict[str, list[str]]:
9+
_execute_system_tests(scenario_map=True, print_stdout=False)
10+
with Path("logs_mock_the_test/scenarios.json").open(encoding="utf-8") as f:
11+
return json.load(f)
12+
13+
714
def run_system_tests(
815
scenario: str = "MOCK_THE_TEST",
916
test_path: str | None = None,
@@ -14,6 +21,37 @@ def run_system_tests(
1421
xfail_strict: bool = False,
1522
env: dict[str, str] | None = None,
1623
expected_return_code: int = 0,
24+
) -> dict[str, dict]:
25+
_execute_system_tests(
26+
scenario=scenario,
27+
test_path=test_path,
28+
verbose=verbose,
29+
forced_test=forced_test,
30+
use_xdist=use_xdist,
31+
xfail_strict=xfail_strict,
32+
env=env,
33+
expected_return_code=expected_return_code,
34+
)
35+
36+
scenario = scenario or "DEFAULT"
37+
with open(f"logs_{scenario.lower()}/feature_parity.json", encoding="utf-8") as f:
38+
report = json.load(f)
39+
40+
return {test["path"]: test for test in report["tests"]}
41+
42+
43+
def _execute_system_tests(
44+
scenario: str = "MOCK_THE_TEST",
45+
test_path: str | None = None,
46+
*,
47+
verbose: bool = False,
48+
forced_test: str | None = None,
49+
use_xdist: bool = False,
50+
xfail_strict: bool = False,
51+
scenario_map: bool = False,
52+
env: dict[str, str] | None = None,
53+
print_stdout: bool = False,
54+
expected_return_code: int = 0,
1755
):
1856
cmd_parts = ["./run.sh"]
1957

@@ -29,15 +67,12 @@ def run_system_tests(
2967
cmd_parts.extend(["-o", "xfail_strict=True"])
3068
if use_xdist:
3169
cmd_parts.extend(["-n=4"])
70+
if scenario_map:
71+
cmd_parts.extend(["--collect-only", "--scenario-report"])
3272

3373
logger.info(" ".join(cmd_parts))
3474
result = subprocess.run(cmd_parts, capture_output=True, text=True, check=False, env=env)
3575

36-
logger.info(result.stdout)
76+
if print_stdout:
77+
logger.info(result.stdout)
3778
assert result.returncode == expected_return_code, f"Command failed with return code {result.returncode}"
38-
39-
scenario = scenario if scenario else "DEFAULT"
40-
with open(f"logs_{scenario.lower()}/feature_parity.json", encoding="utf-8") as f:
41-
report = json.load(f)
42-
43-
return {test["path"]: test for test in report["tests"]}

0 commit comments

Comments
 (0)