make test is effectively a no-op: Go tests are compile stubs, frontend has no test framework
#21
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
REPO_POLICIES.md: "All repos with software must have tests that run via the platform-standard test framework... There is no excuse formake testto be a no-op." Both halves of this repo fail that. Verified onmainatfbfe1df.Frontend: no test framework at all
script/testin its entirety:The script's own comment admits it: "This repo has no unit tests; the production build serves as the test (fails on broken code)." A production bundle asserts nothing about behaviour — it proves the code parses, nothing more.
package.jsondevDependencies contain no test runner: novitest,jest,mocha, or@testing-library/*.package.jsonscriptshas onlydev,build,preview— notestscript.CODE_STYLEGUIDE_JS.mdrequires thatyarn run testandnpm run testboth work; today both fail.*.test.js/*.spec.js/__tests__files exist.Backend: both test files are compile-check stubs
backend/internal/handlers/handlers_test.goandbackend/internal/reportbuf/reportbuf_test.goare 13 lines each and identical in shape:They assert nothing. Coverage by package:
internal/reportbufis 199 lines of buffered zstd compression and flushing — the most logic-dense and most failure-prone package in the repo — and has zero behavioural tests.make testalso lacks the mandated flags and rerun patternbackend/Makefile:test: timeout 30 go test ./...No
-race. No-cover.No conditional-verbose-rerun.
REPO_POLICIES.mdrequires:Grepping the repo for
Rerunningreturns zero hits — the pattern is absent from both the Go and the frontend side.Definition of done
internal/reportbufhas real behavioural tests: append then read back round-trips correctly; zstd output actually decompresses to the input; flush/rotation behaves at the buffer boundary; concurrentAppendis safe under-race; error paths (unwritable target) are handled without panicking.internal/handlershas real tests usinghttptest:HandleReportreturns 200 on a valid body; returns 400 on malformed JSON; rejects a body overmaxReportBodyBytes;HandleHealthCheckreturns the documented JSON shape withContent-Type: application/json.internal/confighas a test proving env-var override and default precedence.TestImportstubs are deleted or replaced — a compile check that duplicates whatgo buildalready proves is not a test.vitestis the default choice — it is the standard runner for a Vite project, shares the Vite config, and needs no separate build pipeline. Do not pick a niche alternative.package.jsongains atestscript soyarn run testworks.humanDurationformatting, the latency-to-colour threshold functions,HostStatemin/max/average/median over a history buffer including the empty and all-unreachable cases, and the health-state classifier's four states.src/main.jscallsinit()at import time, which makes the module hard to import under test. Extracting the pure helpers into importable modules is in scope insofar as it is needed to make them testable; a full modularization of the 1262-line file is not in scope here and is tracked separately.make testimplementations use the conditional-verbose-rerun pattern fromREPO_POLICIES.md, and the Go one adds-raceand-cover.make testcompletes in under 20 seconds with a 30-second timeout enforced, on both sides.make checkandcd backend && make checkboth pass.README.md's TODO no longer lists "Add unit tests"; the Entrypoints description ofscript/testis corrected — it currently describes running the build as the test.TODO.mdupdated in the same commit.(closes #N).Implementation requirements
vitestfor JS; on the Go side prefer stdlibtestingplusnet/http/httptestand do not add an assertion library unless there is a clear reason.make checkmust not modify tracked files.maketargets andscript/entrypoints only.Additional scope: the 30s test timeout is a real Docker-gate flake, not just a policy gap
Surfaced during the review of PR #31 and worth folding into this issue, because it turns an abstract compliance item into a concrete "main always green" problem.
A reviewer's first cold
docker build -f Dockerfile.backend .at head4d70317died here:That is
backend/Makefile'stimeout 30 go test ./.... The cause is an empty Go build cache in a fresh container — compilation alone ate the budget before any test ran. The immediate retry, with a warm cache, compiled in 11 seconds and went green.So the Docker gate can fail for reasons that have nothing to do with the code, on exactly the cold-cache path CI takes most often. That is a false red against the "
mainmust always passmake check" policy, and false reds are corrosive: they train people to re-run rather than read.What this changes about this issue
The existing definition of done already requires adopting the conditional-verbose-rerun pattern and
-race -cover. Add to it:REPO_POLICIES.mdrequiresmake testto complete in under 20 seconds with a 30-second timeout — but that budget is about test execution, not first-compile. Either raise the timeout, or arrange for the build stage to have compiled the packages beforemake testruns, so the timeout measures what it is meant to measure.docker build -f Dockerfile.backend .three times running, all green. One passing run proves nothing here — the flake only appears cold.Note the interaction with
-race: adding it will make compilation slower, not faster. Whatever budget is chosen must be validated with-raceenabled, not before.Also note that
timeout 30uses the externaltimeout(1)binary, which does not exist on stock macOS. Go's own-timeout 30sflag is the portable way to express this and is whatREPO_POLICIES.md's Go example uses. Switching to it fixes the portability problem and makes the timeout apply to test execution rather than to compilation-plus-execution — which is very likely the correct fix for the flake as well.