Test Suite Audit — TODO & Qualification Checklist
Audit performed April 2026. All issues found during a full read of every test file against the source it covers. Fixes applied in the same session where noted; remaining items tracked here.
Qualification Checklist
Run this checklist whenever a test file is touched, a new class is added, or a public API changes. It is not optional.
For every test file
- Every public method on the class under test has at least one passing assertion and at least one rejection/crash assertion (where applicable).
- No test captures values via
$_Out(_OutMode=global). All captures useinto=varname. - No test inspects
__boop_registryor other internal globals directly unless the thing being tested IS the registry (e.g., destroy, serialize). Observable behavior through the public API is always preferred. - Every section description accurately describes what is being tested. Descriptions like “stops on non-zero return” must be unambiguous about edge cases (does the stopping element count?).
- Crash/rejection tests use
bash -cisolation. In-process crash tests are not allowed — they kill the test runner. - Probabilistic tests (shuffle, random ID uniqueness) document their statistical assumptions and have a retry or tolerance strategy that is explicit, not ad-hoc.
- No
|| trueon source lines. Load failures must be loud. - No magic numbers in assertions without a derivation comment.
- Tests that depend on ordering (section A mutates state used by section B) are either eliminated or explicitly documented as sequential dependencies.
For the suite as a whole
- There is a smoke test file that answers “is the framework alive?” in under 2 seconds with no more than 10 assertions.
- The smoke/unit/integration taxonomy is reflected in file names or a manifest. Every test file is classified.
test_allruns smoke first, then unit, then integration. A smoke failure short-circuits the rest.- The naming convention check in
test_allcovers ALL class files and ALL test files, not just the ones listed at the time of writing. boopExtendhas direct test coverage.- Every class added to the hierarchy has a corresponding
_tstest file or is explicitly covered in an existing file with a comment explaining why.
For the TestSuite harness itself
- Both the passing and failing paths of every assertion type are tested (assert_eq pass AND fail, assert_match pass AND fail, etc.).
- The suite isolation test uses a derived bound, not a magic number.
- The stderr capture test verifies the right thing: that the command’s stderr is captured by the harness, not that the harness’s own _Debug output reaches a file.
Issues by File — Status
NEW: test_smoke (missing file) [ ] FIXED
A smoke test file does not exist. Need a file test_smoke that:
- Sources boop and one class
- Creates one object, calls one method, checks the result
- Verifies the framework loaded (registry non-empty)
- Runs in under 2 seconds
- Is the first file run by test_all
test_testsuite_ts [ ] FIXED
-
Stderr capture mechanism is wrong. The test redirects
$t.assert_ok’s stderr to a file, but assert_ok internally redirects the command’s stderr to its own temp file. The outer redirect captures _Debug output from TestSuite, not the command’s stderr. The test passes for the wrong reason. Fix: test that the harness captures stderr from the command under test by verifying the _Debug call receives the right content — test the harness contract, not the fd plumbing. -
Suite isolation uses magic number
< 50. If the suite grows past 50 assertions, this silently becomes wrong. Fix: record the count before running the sub-suite, run it, verify the parent count didn’t change. -
No negative assertion tests. assert_eq failing, assert_match not matching, assert_contains not containing — only happy paths are tested. Fix: add a sub-suite that deliberately fails assertions and verify the failed count increments correctly.
-
assert_ok/assert_fail not tested with commands that produce stdout. Unknown whether stdout from the command under test leaks to the terminal or is suppressed. Fix: add a test with a command that writes to stdout and verify it doesn’t corrupt the test output.
test_box_cube_ts [ ] FIXED
-
No crash/rejection tests.
Cube size=abc,Cubewith no size,Box.calcwith zero — these are in test_adversarial_ts instead of here. Unit tests for a class should be self-contained. Fix: add a “Rejection” section with the crash cases that belong to Box/Cube specifically. -
toString section is thin. Doesn’t verify internal fields are suppressed, doesn’t test Box toString, doesn’t verify field values appear in the output. Fix: expand toString section.
-
_Bless is not directly tested. The bug we just fixed (wrappers baked with wrong _Class after _Bless) had no test. Fix: add an explicit “_Bless” section that creates an object via a parent constructor, blesses it to the child class, and verifies isa, toString, and method dispatch all reflect the blessed class.
-
Mutation section silently corrupts shared state.
$box.set length 10modifies the box used in the geometry section. Fix: use a dedicated mutation object, not the shared fixture.
test_containers_ts [ ] FIXED
-
each early-exit count is ambiguous. The description “stops on non-zero return” doesn’t say whether the stopping element is counted. Fix: rename to “each: callback called for stopping element” and assert 2 explicitly with a comment.
-
deepSet missing-intermediate test description is wrong. The test uses index 99 (out of range), not a missing intermediate container. Fix: write a test that actually has a missing intermediate (e.g., a List whose element is a plain string, not a container) and verify it crashes.
-
Destroy test inspects registry directly. Fix: after destroy, attempt to call a method on the destroyed object and verify it crashes (or verify the wrapper function no longer exists). The registry check is an implementation detail.
-
Map toString test only checks prefix. Fix: verify field values appear in the output.
-
Iterator snapshot isolation asserts count only. Fix: also verify the values returned are the original 3, not 3 arbitrary values.
test_math_ts [ ] FIXED
-
Division precision not verified.
1/3matched with0.333333333*passes even if the result is0.3. Fix: assert the exact digit count matches the configured precision. -
Division by zero not tested. Fix: add
assert_failforMath.divide 5 0. -
Math.DO precedence test is ambiguous.
2 + 3 x 4 = 14is consistent with both “x has higher precedence” and “left-to-right”. Fix: add a test that distinguishes the two:2 x 3 + 4should be 10 if x has higher precedence, 20 if left-to-right. -
mod, pow, toScale, format, isZero not tested. Fix: add sections for each. These are public methods with no coverage.
-
Static API doesn’t cover negative inputs or edge cases. Fix: add
Math.neg -3.14(double negation → positive),Math.abs 0,Math.absof a negative.
test_logging_ts [ ] FIXED
-
“Closed stderr” test description is misleading. “warn with closed stderr fails” — it’s bash that fails on the write, not boop. Fix: rename to “writing to closed stderr propagates write failure”.
-
Fallback log file never tested.
__boop_logFileis set but never exercised. Fix: add a test that closes stderr, calls _Warn, and verifies the fallback file was written. (Or document that the fallback was removed and remove the global.) -
Caller context test bypasses normal dispatch. Fix: call the method through the normal object wrapper (
$box.test_log) and verify the caller name is still correct.
test_adversarial_ts [ ] FIXED
-
File is misnamed. It’s an adversarial/integration test, not a stress test. The benchmark section is opt-in and skipped by default. Fix: rename to
test_framework_tsortest_adversarial_ts. Update test_all. -
Duplicate property test uses $t.info instead of assertion. The behavior of duplicate constructor args is observable. Fix: assert the actual value (last-write-wins or first-write-wins, whichever is correct).
-
Section 12 wrapper test logic is inverted and confusing. The
assert_fail test "${__wrap_def}" != "${__wrap_def/__init/}"pattern is a double-negative that tests string substitution, not the wrapper. Fix: useassert_contains/assert_ok test -zdirectly. -
_Super tests don’t cover multi-level chaining or into=. Fix: add a three-level hierarchy test and verify
into=works with _Super. -
Serialization test doesn’t verify property values after round-trip. Fix: serialize, deserialize in a fresh shell, call
$obj.get property, verify the value. -
$_Outused for object capture at top of file.box="$_Out"andcube="$_Out"afternew. Fix: useinto=boxandinto=cube.
test_blackjack [ ] FIXED
-
. blackjack </dev/null 2>/dev/null || trueswallows load errors. Fix: remove|| true. If blackjack fails to source, the test should fail loudly. -
Shuffle test retry logic is ad-hoc. Fix: document the statistical assumption (probability of a fair Fisher-Yates shuffle leaving >= 8 cards in place is astronomically small) and remove the retry — one shuffle is sufficient. Or keep the retry but make it a loop with a fixed max and a clear failure message.
-
BlackjackHand.deal not tested in the unit section. Fix: add a deal test in the BlackjackHand unit section (not just integration).
-
BlackjackHand.reveal not tested directly. Fix: assert that after reveal,
$h.get faceUpequals the hand length. -
BlackjackHand.cardVal never tested. Fix: add a section that calls cardVal directly for A, J, Q, K, and numeric ranks.
test_all [ ] FIXED
-
Naming convention check doesn’t cover all files. PlayingCard, Deck, Hand, Card, x are not in
__nc_files. Fix: add all class files. -
No smoke-first ordering. Fix: run test_smoke first; if it fails, print a clear message and exit before running the rest.
-
test_adversarial_ts rename. Update the loop and any references when the file is renamed.
Methods with Zero Test Coverage
As of this audit:
| Class | Uncovered methods |
|---|---|
| Math | mod, pow, toScale, format, isZero |
| Math static | mod, pow, toScale, format |
| boop | boopExtend (framework function, not a method) |
| boop | serialize/deserialize property round-trip |
| BlackjackHand | cardVal, reveal (direct) |
| TestSuite | assert_* failure paths (harness self-test) |
| Container | noIterators |
Notes
test_matrixandtest_pi_growthare benchmarks, not test suites. They are correctly excluded fromtest_all. No changes needed.- The
xfile in the workspace root is unknown — not covered by any test or naming check. Investigate before next push. - README.md test counts will need updating after fixes (currently says 488, actual is higher after recent additions).