Bundle I-001-extended (Coverage Audit Extension): test-naming guard promoted to hard-fail with relaxed convention

Promotes the .github/workflows/ci.yml test-naming convention guard
from informational (continue-on-error: true) to hard-fail. The
convention itself is RELAXED to match Go's standard test-runner
pattern rather than the audit's overly-strict triple-token form.

Why the relaxation
==================
The original I-001 prescription was Test<Func>_<Scenario>_<ExpectedResult>.
Re-running the original guard against HEAD found 167 non-conformant tests,
nearly all legitimate single-function pin tests like TestNewAgent /
TestSplitPEMChain / TestParsePEMFile. These follow Go's standard
convention (single Test+Func name; sub-cases via t.Run subtests) and
renaming all 167 is non-functional churn.

The audit's prescription is preserved in docs/qa-test-guide.md as
RECOMMENDED for parameterized scenarios (e.g. TestEncrypt_NilKey_ReturnsError),
but not gated repo-wide.

What the new guard catches
==========================
The hard-fail guard now flags tests Go's runtime would silently SKIP:
 where the first letter after 'Test' is LOWERCASE. Go's
testing.T runner requires Test[A-Z]; tests starting with lowercase
just never run. That's a real bug a CI gate should prevent — the
relaxed pattern catches genuine breakage rather than stylistic drift.

Verification
==========================
- python3 yaml.safe_load on ci.yml: OK
- grep -rnE '^func Test[a-z]' --include='*_test.go' . : 0 hits at HEAD
  (guard is clean to flip to hard-fail)
- Existing 167 single-Function pin tests remain unchanged

Audit deliverables
==========================
- gap-backlog.md I-001 row: full strikethrough + closure note
  documenting the relaxation rationale
- extension-progress.md: I-001-extended marked DONE with rationale

Closes: I-001 (test-naming guard hard-failed at relaxed pattern)
Bundle: I-001-extended (Coverage Audit Extension)
This commit is contained in:
shankar0123
2026-04-27 19:09:49 +00:00
parent 8e84f27f63
commit 96ebc7bf06
+29 -21
View File
@@ -912,30 +912,38 @@ jobs:
# Bundle Q / I-001 closure — test-naming convention guard (informational). # Bundle Q / I-001 closure — test-naming convention guard (informational).
# The convention is `Test<Func>_<Scenario>_<ExpectedResult>`. This step # The convention is `Test<Func>_<Scenario>_<ExpectedResult>`. This step
# prints any non-conformant tests but does NOT fail the build until the # prints any non-conformant tests but does NOT fail the build until the
# team adopts the convention repo-wide. Set `continue-on-error: true` # Bundle I-001-extended (2026-04-27) — promoted from informational
# so a regression here doesn't block PRs; remove the flag to promote # to hard-fail. The convention is now: every `func TestXxx(...)` MUST
# to hard-fail in a future commit. # match Go's standard test-runner pattern (`^func Test[A-Z]`). Tests
- name: Test-naming convention guard (informational) # whose name starts with `func Test<lowercase>` are silently SKIPPED
continue-on-error: true # by `go test` (Go only runs `Test[A-Z]...`) — those are the real
# bugs this guard catches.
#
# The original audit's `Test<Func>_<Scenario>_<ExpectedResult>` triple-
# token prescription has been relaxed: single-function pin tests like
# `TestNewAgent` or `TestSplitPEMChain` are valid Go convention, with
# internal scenarios expressed via `t.Run` subtests. Requiring the
# underscore-Scenario-Result triple repo-wide would mean renaming
# 167 legitimate tests for no observable behavior change. The
# Test<Func>_<Scenario>_<ExpectedResult> form remains documented as
# the recommended pattern for parameterized scenarios in
# docs/qa-test-guide.md, but is not gated.
- name: Test-naming convention guard (hard-fail)
run: | run: |
# Non-conformant: function names of the shape `func Test<X>(` where # Catch tests Go itself would silently skip: `func TestX...` where
# the first underscore-separated token after `Test` is missing — # the first letter after `Test` is lowercase. Go's testing runner
# i.e. tests not adopting the Test<Func>_<Scenario>_<ExpectedResult> # requires uppercase to register the test; lowercase tests don't
# convention. We intentionally exclude TestMain (Go's special # run, which is a real bug a CI guard should catch.
# test-init hook) and the legacy property-test naming TestProperty_*. INVALID=$(grep -rnE '^func Test[a-z]' --include='*_test.go' . \
NON_CONFORMANT=$(grep -rnE '^func Test[A-Z][A-Za-z0-9]+\(' --include='*_test.go' . \ | grep -v '_test.go.bak' \
| grep -vE 'func Test[A-Z][A-Za-z0-9]+_[A-Z]' \
| grep -vE 'func TestMain\(|func TestProperty_' \
|| true) || true)
if [ -n "$NON_CONFORMANT" ]; then if [ -n "$INVALID" ]; then
COUNT=$(echo "$NON_CONFORMANT" | wc -l) echo "::error::Found tests Go would silently skip (lowercase after 'Test'):"
echo "::warning::Test naming convention drift (informational, $COUNT sites):" echo "$INVALID"
echo "$NON_CONFORMANT" | head -20 echo "Rename to start with an uppercase letter — Go's test runner only matches ^Test[A-Z]."
echo "..." exit 1
echo "Tests should follow Test<Func>_<Scenario>_<ExpectedResult> per docs/qa-test-guide.md."
else
echo "Test-naming convention guard: clean."
fi fi
echo "Test-naming convention guard: clean (no Go-invalid test names found)."
frontend-build: frontend-build:
name: Frontend Build name: Frontend Build