Add focused changed-path test wrapper
This commit is contained in:
@@ -13,6 +13,21 @@ This repository tests its configuration at defined seams. The tests run with `ba
|
|||||||
| Script syntax | `tests/scripts_syntax.bats` | `bash -n` clean, executable bits, shellcheck when available |
|
| Script syntax | `tests/scripts_syntax.bats` | `bash -n` clean, executable bits, shellcheck when available |
|
||||||
| Deployment flow | `tests/deployment_flow.bats` | deploy.sh exists, targets known, SSH reachable (skips offline) |
|
| Deployment flow | `tests/deployment_flow.bats` | deploy.sh exists, targets known, SSH reachable (skips offline) |
|
||||||
|
|
||||||
|
## Focused pre-commit testing
|
||||||
|
|
||||||
|
For normal commits, use the focused wrapper:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/test-changed.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
It reads staged paths with `git diff --cached` and runs only the mapped Bats
|
||||||
|
files. Use `--list` to inspect the selection without running tests, or
|
||||||
|
`--paths FILE ...` to preview a mapping. Shared test infrastructure and
|
||||||
|
unmapped paths fail closed rather than silently skipping coverage. Run the
|
||||||
|
full suite with `./tests/run.sh` when changing shared test helpers, the test
|
||||||
|
runner, or when focused coverage is not sufficient.
|
||||||
|
|
||||||
## Red-Green
|
## Red-Green
|
||||||
|
|
||||||
Tests are written first. A failing test means the seam is not satisfied; the config change that makes it pass is the only acceptable fix. No `--no-verify`, no deleting tests without approval.
|
Tests are written first. A failing test means the seam is not satisfied; the config change that makes it pass is the only acceptable fix. No `--no-verify`, no deleting tests without approval.
|
||||||
|
|||||||
Executable
+142
@@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Run only the Bats tests affected by the staged paths.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# scripts/test-changed.sh # inspect the staged commit
|
||||||
|
# scripts/test-changed.sh --list # print selected test files
|
||||||
|
# scripts/test-changed.sh --paths FILE ...
|
||||||
|
#
|
||||||
|
# --paths is intended for tests and local experimentation. The normal mode is
|
||||||
|
# deliberately staged-only so a pre-commit hook cannot accidentally validate
|
||||||
|
# an unrelated dirty working-tree file.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
LIST_ONLY=0
|
||||||
|
USE_PATHS=0
|
||||||
|
declare -a CHANGED=()
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf 'ERROR: %s\n' "$*" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ "$#" -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--list)
|
||||||
|
LIST_ONLY=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--paths)
|
||||||
|
USE_PATHS=1
|
||||||
|
shift
|
||||||
|
while [ "$#" -gt 0 ] && [[ "$1" != --* ]]; do
|
||||||
|
CHANGED+=("$1")
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
CHANGED+=("$@")
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "unknown option '$1' (use --list or --paths FILE ...)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
if [ "$USE_PATHS" -eq 0 ]; then
|
||||||
|
while IFS= read -r -d '' path; do
|
||||||
|
CHANGED+=("$path")
|
||||||
|
done < <(git diff --cached --name-only -z --diff-filter=ACMRTUXB)
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ "${#CHANGED[@]}" -gt 0 ] || {
|
||||||
|
printf 'No staged paths; no focused tests to run.\n'
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare -a TESTS=()
|
||||||
|
add_test() {
|
||||||
|
local test="$1"
|
||||||
|
local existing
|
||||||
|
for existing in "${TESTS[@]:-}"; do
|
||||||
|
[ "$existing" != "$test" ] || return 0
|
||||||
|
done
|
||||||
|
TESTS+=("$test")
|
||||||
|
}
|
||||||
|
|
||||||
|
for path in "${CHANGED[@]}"; do
|
||||||
|
case "$path" in
|
||||||
|
tests/*.bats)
|
||||||
|
add_test "$path"
|
||||||
|
;;
|
||||||
|
tests/helpers.bash|tests/run.sh)
|
||||||
|
die "$path is shared test infrastructure; run ./tests/run.sh explicitly"
|
||||||
|
;;
|
||||||
|
dankserver/compose.yaml|dankclaw/compose.yaml)
|
||||||
|
add_test tests/compose_validity.bats
|
||||||
|
add_test tests/env_consistency.bats
|
||||||
|
;;
|
||||||
|
dankserver/Caddyfile|dankclaw/Caddyfile)
|
||||||
|
add_test tests/caddyfile.bats
|
||||||
|
;;
|
||||||
|
dankserver/.env.example|dankclaw/.env.example)
|
||||||
|
add_test tests/env_consistency.bats
|
||||||
|
;;
|
||||||
|
shared/homepage/*)
|
||||||
|
add_test tests/homepage_caddy.bats
|
||||||
|
add_test tests/homepage_config.bats
|
||||||
|
add_test tests/homepage_deploy.bats
|
||||||
|
add_test tests/homepage_pages.bats
|
||||||
|
add_test tests/homepage_checker.bats
|
||||||
|
;;
|
||||||
|
shared/searxng/*)
|
||||||
|
add_test tests/searxng_limiter.bats
|
||||||
|
add_test tests/searxng_quadlet.bats
|
||||||
|
;;
|
||||||
|
dankclaw/*.container|dankclaw/*.network)
|
||||||
|
add_test tests/open_webui_quadlet.bats
|
||||||
|
add_test tests/pihole.bats
|
||||||
|
add_test tests/searxng_quadlet.bats
|
||||||
|
;;
|
||||||
|
scripts/mount-entropy.sh)
|
||||||
|
add_test tests/mount_entropy.bats
|
||||||
|
;;
|
||||||
|
scripts/frank-default-large.env|scripts/serve-frank-large.sh)
|
||||||
|
add_test tests/frank_large_config.bats
|
||||||
|
add_test tests/llm_secrets.bats
|
||||||
|
add_test tests/scripts_syntax.bats
|
||||||
|
;;
|
||||||
|
scripts/frank-default-small.env|scripts/serve-frank-small.sh)
|
||||||
|
add_test tests/frank_small_config.bats
|
||||||
|
add_test tests/llm_secrets.bats
|
||||||
|
add_test tests/scripts_syntax.bats
|
||||||
|
;;
|
||||||
|
scripts/*.service)
|
||||||
|
add_test tests/llm_units.bats
|
||||||
|
add_test tests/scripts_syntax.bats
|
||||||
|
;;
|
||||||
|
scripts/*)
|
||||||
|
add_test tests/scripts_syntax.bats
|
||||||
|
;;
|
||||||
|
docs/*)
|
||||||
|
add_test tests/docs_completeness.bats
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "no focused-test mapping for '$path'; add one before committing"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$LIST_ONLY" -eq 1 ]; then
|
||||||
|
printf '%s\n' "${TESTS[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v bats >/dev/null 2>&1 || die 'bats is not installed'
|
||||||
|
printf 'Running focused tests for %d changed path(s):\n' "${#CHANGED[@]}"
|
||||||
|
printf ' %s\n' "${TESTS[@]}"
|
||||||
|
bats --print-output-on-failure "${TESTS[@]}"
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
# Seam: the changed-test wrapper selects only the tests associated with
|
||||||
|
# staged paths and refuses to silently run the entire suite.
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
@test "changed-test wrapper is executable and uses staged diff by default" {
|
||||||
|
[ -x "$REPO_ROOT/scripts/test-changed.sh" ]
|
||||||
|
run grep -F 'git diff --cached' "$REPO_ROOT/scripts/test-changed.sh"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "changed-test wrapper maps a compose change to compose and environment tests" {
|
||||||
|
run bash "$REPO_ROOT/scripts/test-changed.sh" --list --paths dankserver/compose.yaml
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"tests/compose_validity.bats"* ]]
|
||||||
|
[[ "$output" == *"tests/env_consistency.bats"* ]]
|
||||||
|
[[ "$output" != *"tests/homepage_pages.bats"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "changed-test wrapper maps a service script to its focused config tests" {
|
||||||
|
run bash "$REPO_ROOT/scripts/test-changed.sh" --list --paths scripts/serve-frank-small.sh
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"tests/scripts_syntax.bats"* ]]
|
||||||
|
[[ "$output" == *"tests/frank_small_config.bats"* ]]
|
||||||
|
[[ "$output" != *"tests/frank_large_config.bats"* ]]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user