Fix #73: regression-test.sh could not go red; reports green having run nothing - #78
Conversation
|
#77 ( Comparing what each fixes:
Verified by running #77's head unmodified: zero tests executed, Suggested handling: land #77 first, then re-apply the four remaining fixes on top of its version. Merging this first would have those changes reverted by #77. If you would rather land this one first, that is fine too — it is correct against current The new test file |
957a982 to
f1401f2
Compare
The combined tree (#77 + #74 + #78) exposed a defect neither PR's CI could see. #77's parser recognises only the Jest "Tests: N passed" form, and #77 alone never exercises it — the unit suite always skipped, so the parser was dead code. #78 makes the suite actually run, and this repo's own shell tests print "Results: 13 passed, 0 failed" with no "Tests:" prefix. A fully green run was therefore reported "no parseable test summary" and exited 1. That is a false RED — the mirror image of the false GREEN #73 is about, and just as damaging: a gate that cannot be trusted in either direction. The fix (in the merge commit) adds a bare "<N> passed" fallback, mirroring the two-tier approach #77's own E2E block already uses. These assertions pin both directions so neither can regress: - a non-Jest "Results: N passed, M failed" summary is accepted (exit 0, not reported as unparseable) - output with no counts at all is STILL an error — the fallback widens the accepted formats without defeating #77's guard against a runner that never produced a summary Verification on the combined tree: - tests/test_regression_test_config.sh: 16/16 - all tests/test_*.sh: 15/15 - pytest: 124/124 - detect_skip_reason present 3x (definition + Unit Tests + E2E guards) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both summary lines printed only "$PASSED/$TOTAL passed" in green, discarding $UNIT_STATUS. On a failed run — especially the "no parseable test summary" case — the reason was written to the report file and never shown, so an operator watching the run saw a green "0/0 passed" and no explanation. Now prints the status and colours the label by outcome, so a red run is visibly red at the point a human is actually looking. Verification: tests/test_regression_test_config.sh 16/16 (the last assertion covers exactly this — an unparseable summary must be *reported*, not merely exit non-zero); all tests/test_*.sh 18/18; pytest 59/59; BUILD_OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
f1401f2 to
9224d98
Compare
Conflict resolution prepared, plus a correction and one new finding1. The resolution (what you asked for)Reproduced the merge locally ( Kept from #78: Kept from #77: both Acceptance on the combined tree: 2. Your diagnosis was right, but the cause was not the dropped guardsTaking #78 wholesale does drop both guards — but that is not what produced The real cause: #77's unit stat parser only recognises the Jest That is a false RED — the mirror image of the false green #73 is about, and it would have bitten the moment the combined tree ran its own suite. Fixed with a bare 3. Correction — I broke this PR and have restored itI pushed the merged branch to This PR is now restored to 3 files / +460 / −27 against current The resolution is preserved locally on 4. One extra fix includedBoth summary lines printed only |
|
Retargeted 🤖 Autonomous fix workflow |
…86) regression-test.sh reported "7/0 passed" for a green run of 178 assertions across 11 suites. Root cause: count_before() ended in `tail -1`, taking the last "<N> passed" in the log. Correct for Jest/Playwright, which emit one summary per run; wrong for this repo's unit command, which loops over a dozen independent bash scripts that each print their own "Results: N passed, M failed". The denominator was worse — no bash suite prints the word "total", so UNIT_TOTAL was always the literal 0. Changes: - count_before() sums matches via awk instead of tail -1. It still returns EMPTY when nothing matched, which the no-parseable-summary guard depends on to distinguish "runner never ran" from a real zero. - UNIT_TOTAL is derived from passed+failed only when the runner reports no total, and only AFTER that guard, so an unparseable run cannot synthesise 0+0=0 and read as green. A total the runner did report is never overwritten — Jest's includes skipped tests. - Mirrored both into .agent/scripts/regression-test.sh per the parallel maintenance requirement in CLAUDE.md. Scope: reporting only, not a false green. UNIT_EXIT comes from PIPESTATUS, and the failure path is unaffected because `|| exit 1` makes a failing script the last summary in the log. Verification: two new fixtures in tests/test_regression_test_config.sh pin both directions (green suites sum to 26/26; failing suites sum to 9/14 and still exit non-zero). Suite 21/21. Full regression now reports 178/178, exit 0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes #73
The important one first: the runner could not fail
That takes the exit status of
tee, not of the suite — andteeessentially always succeeds. This script has noset -o pipefail, so every failing unit and E2E run on master was recorded as ✅ PASSED with exit 0.Demonstrated:
And end-to-end against a deliberately failing suite, before the fix:
RC=0,✅ All tests passed!A quality gate that cannot go red is worse than no gate —
/fixand/devtreat a green regression run as licence to move on to enhancements.Fixed with
${PIPESTATUS[0]}, deliberately not with a globalset -o pipefail. This script has many other pipelines (grep|head,grep|sed) whose failures are currently benign; flippingpipefailunderset -ewould start aborting runs on those. PIPESTATUS is applied at the two places correctness depends on it.The other four
REPORT_DIRglob. Took the firstLocation:line anywhere inCLAUDE.md— the Unit Tests one (tests/test_*.sh), a glob.mkdir -pcreated a directory whose literal name contained an asterisk, which then matchedtests/test_*.shexpansions and broke callers iterating the shell suites. Now scoped byawkto the**Test Reports**:block, with a guard rejecting glob metacharacters and...Dead extraction path. The unit-test command was read from
### Unit Tests Only, but gated behind aWorking directory:check that noCLAUDE.mdsatisfies — so extraction never ran and the suite silently skipped. Now reads the header directly, falling back to### Regression Test Suite, with a self-reference guard: in this repo that entry is this script, so adopting it would recurse without bound.CLAUDE.mdgains the### Unit Tests Onlyblock the script has always documented. The repo's 14 shell suites now actually run.All-skipped counted as passed. Zero tests executed is not a pass; exits 1 and says why.
Environment leak. The runner exported its own
ISSUE_SOURCEinto the suite.issue-config.shtreats a pre-setISSUE_SOURCEas authoritative and skips.autocoder.json, so tests building a file-backend fixture would talk to the live tracker. Suites now run underenv -u ISSUE_SOURCE -u ISSUE_DIR_PATH -u ISSUE_BACKEND.Extraction uses
awk, not a nestedsedrange: BSDsed(macOS) rejects/a/,/b/{/c/,/d/p}outright, which aborts the run underset -e.Also adds
REGRESSION_TEST_NO_ISSUES=1so the suite can exercise the runner without touching a real tracker, and makes a failing tracker query (no remote, no auth) non-fatal rather than aborting a run whose tests already passed.Verification
The new test file includes an explicit assertion that a failing suite exits non-zero — the property that was silently broken. Confirmed it fails against the pre-fix script and passes after.
Runner on this repo now executes the 14 shell suites, reports the real result, writes to
docs/test/regression-reports/, and creates no glob directory. Remote tree OID verified identical to local HEAD tree (d8ff1033).Known remaining gap (not fixed here)
The summary line prints counts like
7/0 passed— the parser keys off Jest/Playwright phrasing and doesn't understand this repo's=== N passed, M failed ===format. The exit code is now authoritative and correct, so this is cosmetic, but it is the same family of misleading-confidence bug and worth a follow-up.🤖 Generated with Claude Code