Finalize ConfigKit design and implementation plan
This commit is contained in:
@@ -2,17 +2,7 @@
|
||||
|
||||
**Base Policy Version:** 1.0
|
||||
|
||||
**Last Updated**: 2026-09-06
|
||||
|
||||
## Base Policy Template
|
||||
|
||||
This document is the base template for the canonical testing policy,. Repositories that implement this policy should:
|
||||
|
||||
1. Review the policy, remove any rules that must not apply to the current project, and add any additional rules that are required by the current project;
|
||||
2. Update the `Last Updated` field to the current date; and
|
||||
3. Remove this heading (`Base Policy Template`) and the associated text.
|
||||
|
||||
Most projects will not require any revisions to the substantive testing policy rules as written below.
|
||||
**Last Updated:** 2026-09-06
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -20,6 +10,29 @@ Our tests exist to make **incorrect changes expensive and correct changes cheap*
|
||||
|
||||
We do not optimize for test count, line coverage, exhaustive isolation, or the fewest possible tests. We optimize for sufficient confidence in important behavior while imposing as little unnecessary friction as possible on future development.
|
||||
|
||||
## ConfigKit-specific priorities
|
||||
|
||||
Configuration semantics are compatibility contracts, even when Go signatures do
|
||||
not change. Apply the risk rules below especially to presence/default behavior,
|
||||
composition, provenance, and error classification. Keep detailed behavior cases
|
||||
with their owning contracts and tests rather than duplicating them in this policy.
|
||||
|
||||
Use real temporary files for import traversal, symlinks, and source identity.
|
||||
Document platform prerequisites for filesystem cases and make any unsupported
|
||||
case explicit rather than silently dropping its coverage. Use labeled in-memory
|
||||
input where filesystem behavior is irrelevant.
|
||||
|
||||
Verify agreement among final resolved values, presence, provenance, and effective
|
||||
rendering. Protect against secret disclosure on both successful inspection and
|
||||
failure paths, and against mutable defaults or results leaking across loads.
|
||||
Use focused fuzzing for parser boundaries and semantic/filesystem path handling;
|
||||
keep deterministic seed regressions in the ordinary suite. Extended fuzz runs
|
||||
need a documented bounded invocation when introduced.
|
||||
|
||||
Baseline commands belong in the [development guide](../development.md). Release
|
||||
gates belong in the [release policy](release.md) and its eventual runbook. This
|
||||
policy does not imply that those tools or tests already exist.
|
||||
|
||||
## Every test has a cost
|
||||
|
||||
Testing is not an unqualified good. Every test imposes both an immediate cost and a continuing lifetime cost.
|
||||
@@ -59,7 +72,8 @@ Use a **classical/Detroit-style** approach:
|
||||
- Prefer package-level behavioral tests over tests coupled to private helpers or internal call sequences.
|
||||
- Treat exact collaborator interactions as testable behavior only when the interaction itself is a requirement.
|
||||
|
||||
Examples of appropriate seams include clocks, randomness, subprocesses, remote APIs, object storage, email, and paid LLM calls.
|
||||
For ConfigKit, controlled input readers and filesystem failures are useful seams.
|
||||
Prefer actual parsing, composition, and decoding over mocks of their call order.
|
||||
|
||||
## Test execution requirements
|
||||
|
||||
@@ -176,13 +190,15 @@ Use a test-controlled limit and measure the behavior relative to that limit. Do
|
||||
|
||||
Each behavior should have a clear test owner.
|
||||
|
||||
- Parser tests own parsing cases.
|
||||
- Validator tests own validation rules.
|
||||
- Domain tests own transformations and invariants.
|
||||
- Adapter tests own external integration behavior.
|
||||
- Orchestrator tests own coordination and failure propagation.
|
||||
- CLI tests own argument and configuration mapping.
|
||||
- End-to-end tests prove that representative assembled workflows work.
|
||||
- YAML boundary tests own syntax and policy enforcement.
|
||||
- Composition and overlay tests own their operation semantics.
|
||||
- Decoding tests own type binding, defaults, and strictness.
|
||||
- Metadata and rendering tests own provenance queries and safe inspection.
|
||||
- Filesystem tests own source access and import identity behavior.
|
||||
- Lifecycle tests own hook ordering, failure propagation, and representative
|
||||
agreement across the assembled configuration pipeline.
|
||||
|
||||
These are responsibility boundaries, not a required package layout.
|
||||
|
||||
Higher-level tests should not repeat every lower-level case. A single intentional policy change should not require unrelated edits across many test files.
|
||||
|
||||
@@ -215,7 +231,6 @@ Use:
|
||||
|
||||
- table-driven tests for meaningful behavioral categories and boundaries;
|
||||
- `t.TempDir()` for real filesystem behavior;
|
||||
- `httptest.Server` for realistic HTTP interactions;
|
||||
- fuzz tests for parsers, normalization, path handling, and broad input spaces;
|
||||
- golden files only when the complete output is intentionally stable;
|
||||
- integration tests where correctness depends on component interaction; and
|
||||
@@ -223,7 +238,8 @@ Use:
|
||||
|
||||
Avoid exact error-string assertions unless the wording is itself contractual. Prefer `errors.Is`, `errors.As`, typed errors, or structured error fields.
|
||||
|
||||
At CLI boundaries, prefer exit classifications, structured output, and the smallest stable semantic fragment needed to identify the error. Do not snapshot complete diagnostic wording unless it is contractual.
|
||||
At the public library boundary, prefer diagnostic codes, paths, and source
|
||||
locations over complete message snapshots. Assert wording only when contractual.
|
||||
|
||||
Golden-file updates must require an explicit local flag. CI must not update golden files automatically, and reviewers must inspect the semantic diff before accepting an update.
|
||||
|
||||
@@ -235,7 +251,7 @@ Coverage is a diagnostic, not a target.
|
||||
|
||||
Use it to find untested critical branches and unexpectedly weak packages. Do not write low-value tests solely to increase a percentage, and do not infer test quality from coverage alone.
|
||||
|
||||
Pure domain logic will often warrant higher coverage than CLI wiring or external adapters. Uneven coverage is acceptable when it reflects risk.
|
||||
Dense configuration semantics will often warrant higher coverage than simple input wiring. Uneven coverage is acceptable when it reflects risk.
|
||||
|
||||
Increasing coverage is valuable only when the newly covered behavior protects a meaningful risk at an acceptable cost.
|
||||
|
||||
@@ -303,7 +319,7 @@ A test suite is sufficient when:
|
||||
- legitimate internal changes usually do not require test edits; and
|
||||
- additional tests would mostly repeat existing protection or preserve inconsequential implementation details.
|
||||
|
||||
Sufficiency is a risk judgment, not a coverage percentage or test count. Reassess it as the application, its users, and the consequences of failure evolve.
|
||||
Sufficiency is a risk judgment, not a coverage percentage or test count. Reassess it as the library, its consumers, and the consequences of failure evolve.
|
||||
|
||||
The governing rule is:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user