# Internal Package Unit Test Coverage

> Status: canonical-spec
> Canonical path: `specs/internal/package-unit-test-coverage.md`
> Scope: unit test coverage policy for `github.com/tidbcloud/AgentTeam/internal/...` Go packages
> Non-goals: coverage thresholds for individual functions or files

## Goal

Every `github.com/tidbcloud/AgentTeam/internal/...` Go package must contain at least one
package-level `Test*` function exercising package behavior. A repeatable
guardrail proves no internal package is left without test coverage.

## Policy

- Each `internal/...` Go package MUST have at least one Go test file
  (`*_test.go`) containing a top-level `func Test...` declaration. The
  guardrail scans `TestGoFiles` and `XTestGoFiles` and matches the regex
  `^\s*func\s+Test[A-Za-z0-9_]*\s*\(`.
- Tests MUST exercise behavior. Empty compile-only placeholders,
  `t.Skip`-only bodies, and tests that assert nothing are not acceptable
  substitutes for coverage.
- When a new `internal/...` package is added, the same change set MUST add
  a behavior test so the guardrail does not regress.
- Coverage of behavior lives in package-specific tests. The guardrail
  intentionally does not enforce runtime behavior itself.

## Guardrail

The authoritative inventory source is
`guardrails/internal/check-internal-package-tests.py`.

The guardrail:

- Runs `go list -json ./internal/...` across the complete internal package tree.
- Reads each package's `TestGoFiles` and `XTestGoFiles`, scanning for
  `func Test...` declarations.
- Reports packages with no matching test function as `MISSING <import path>`.

### Invocation

- Default (no flag): the guardrail fails if any `internal/...` package lacks
  a `Test*` function. This is the steady-state target.
- `--expect-missing N`: the guardrail passes only when exactly `N` internal
  packages are missing test coverage, and fails otherwise. This is the
  staged-lock mechanism used while the count is being driven toward zero;
  `N` may only decrease over time.

### Current state

The current missing-package count on `origin/main` is whatever
`guardrails/internal/check-internal-package-tests.py` reports when invoked.
The guardrail output is authoritative; any number cited in this spec or
elsewhere is descriptive only and may drift between commits.

## Verification

Repeatable verification for changes touching this area:

- `python3 guardrails/internal/check-internal-package-tests.py`
- `python3 guardrails/internal/check-internal-package-tests.py --expect-missing N`
  where `N` matches the current count when the staged lock is in effect.
- `git diff --check`

Reducing the staged-lock count requires adding behavior tests for at least
one currently-missing package and lowering `N` in the same change set.
Tests added for this purpose MUST exercise real package behavior, not
compile-only placeholders.

## Non-goals

- This spec does not set function-level or line-level coverage thresholds.
- This spec does not prescribe test style beyond the requirement that
  tests exercise behavior. Table-driven, httptest-backed, fake-driven,
  and sql-test-driver styles are all acceptable.
