Summary
The same foreach (['python3', 'python'] as $candidate) { $which = shell_exec("which {$candidate} 2>/dev/null"); ... } interpreter-discovery block, followed by a skip-or-fail decision, is duplicated across three test files with small, real divergences:
tests/Unit/Bridge/PythonBridgeTest.php:52-60 — discovers, then always markTestSkipped() if absent (no CI-fail branch)
tests/Feature/GateParityTest.php:21-33 — discovers, then test()->fail(...) if getenv('CI') !== false, else skip
tests/Feature/CustomProviderTest.php:22-49 (inside a named helper customProviderPythonPath()) — additionally checks getenv('AETHER_PYTHON_PATH') first, then the same discovery loop, then the same CI-fail-else-skip branch
Where
tests/Unit/Bridge/PythonBridgeTest.php:52-60
tests/Feature/GateParityTest.php:21-33
tests/Feature/CustomProviderTest.php:22-49
Refactor proposal
Add one shared helper to tests/Pest.php (e.g. resolveTestPythonPath(bool $requireInCi = true): ?string), honoring AETHER_PYTHON_PATH first, then falling back to the which python3/python search, with the CI-fail-vs-skip decision as a parameter — then have all three test files call it instead of carrying their own (subtly different) copies.
Severity: low
Summary
The same
foreach (['python3', 'python'] as $candidate) { $which = shell_exec("which {$candidate} 2>/dev/null"); ... }interpreter-discovery block, followed by a skip-or-fail decision, is duplicated across three test files with small, real divergences:tests/Unit/Bridge/PythonBridgeTest.php:52-60— discovers, then alwaysmarkTestSkipped()if absent (no CI-fail branch)tests/Feature/GateParityTest.php:21-33— discovers, thentest()->fail(...)ifgetenv('CI') !== false, else skiptests/Feature/CustomProviderTest.php:22-49(inside a named helpercustomProviderPythonPath()) — additionally checksgetenv('AETHER_PYTHON_PATH')first, then the same discovery loop, then the same CI-fail-else-skip branchWhere
tests/Unit/Bridge/PythonBridgeTest.php:52-60tests/Feature/GateParityTest.php:21-33tests/Feature/CustomProviderTest.php:22-49Refactor proposal
Add one shared helper to
tests/Pest.php(e.g.resolveTestPythonPath(bool $requireInCi = true): ?string), honoringAETHER_PYTHON_PATHfirst, then falling back to thewhich python3/pythonsearch, with the CI-fail-vs-skip decision as a parameter — then have all three test files call it instead of carrying their own (subtly different) copies.Severity: low