Close bats coverage gaps, add hide_command helper, wire up kcov

- tests/helpers/common.bash: hide_command hides python3/jq/rg via a
  per-directory-batched PATH shim (not per-file — that took minutes),
  making the fail-open/grep-fallback branches testable.
- 20 new tests across all 7 .bats files: unknown flags, invalid
  --settings-scope, missing python3/jq, grep fallback when rg is
  unavailable, empty/multi-vault config edge cases, a vault path that
  stops existing or isn't a directory, and the previously-untested
  tool_name != Bash branch of force-ask-on-raw-git.sh. 53 -> 73 tests.
- hooks.bats: deploy the hooks once in setup_file() (BATS_FILE_TMPDIR)
  instead of per-test (BATS_TEST_TMPDIR) -- faster, and gives kcov one
  stable path per hook to aggregate coverage against instead of a
  fragmented copy per test.
- .gitignore (first in this repo) + tests/README.md Coverage section
  documenting the kcov invocation and why --include-pattern needs three
  entries, not two.

Real, tool-measured coverage via kcov: 86.15% (255/296 lines) across
all 10 wrapper/setup/hook scripts in both plugins, replacing an earlier
manual ~68% branch-coverage estimate.
This commit is contained in:
Henner M. Kruse
2026-08-04 21:09:07 +00:00
parent 2d25e69632
commit dc4a5c5b5e
10 changed files with 218 additions and 5 deletions
+22
View File
@@ -37,3 +37,25 @@ under test. Since every script here resolves its config from
There's no CI wiring for this suite yet — run it manually before/after
touching anything under `skills/` or `vendor/claude-code/plugins/`.
## Coverage
```bash
sudo apt install kcov # or a user-local install, as done for bats
kcov --include-pattern=/repo/skills/,/repo/vendor/claude-code/plugins/,force-ask-on-chaining.sh,force-ask-on-raw-git.sh \
tests/coverage bats -r tests/
```
Opens as `tests/coverage/bats.<hash>/index.html` (not committed — see
`.gitignore`). `kcov` follows every bash subprocess `bats` forks, so this
covers the actual wrapper/setup/hook scripts, not just `bats` itself.
The `--include-pattern` needs three things, not just the two source
directories: `git_cmd.sh`/`vault_*.sh`/`setup.sh` run straight from this
checkout, so `/repo/skills/` and `/repo/vendor/claude-code/plugins/` catch
them (the leading `/repo/` matters — a plain `skills/` would also match this
repo's own outer directory name and pull in unrelated files). The two
`PreToolUse` hooks are different: `tests/git-manager/hooks.bats` exercises
the *deployed* copies under `~/.agent-skills/git-manager/bin/` (matching how
Claude Code actually invokes them), which live outside both of those
directories — hence matching them by filename instead.