Table-driven tests
Use table-driven tests when cases share setup and assertions. Addt.Run so each case is reported by name.
Naming
Name test functionsTest<Type>_<Behavior> or Test<Function>_<Scenario>. Name table cases so failures read like a sentence.
Prefer names that state the guarantee under test. TestParseURN_RejectsCrossWorkspaceResources is better than TestParseURN_InvalidInput because it tells the reader which production boundary the test protects.
Add a docstring when the guarantee is not obvious from the name. Use the docstring to explain the invariant, regression, or business rule, not the steps the test performs.
Parallel execution
Uset.Parallel() only when tests do not share mutable state or external resources.
Helpers and cleanup
Helpers that assert must callt.Helper(). Use t.Cleanup() for resource cleanup so subtests complete before cleanup runs.
Helpers are production test APIs. Keep them small, typed, and named after the domain object or state they create. If a helper hides important setup, document the guarantee it establishes for callers.
Test data
Inline small fixtures. Usetestdata/ for larger files and include them in Bazel targets.
Name fixtures by the behavior they exercise. A fixture named expired_root_key.json is better than case_3.json because it carries the test guarantee into the filesystem.
Time-dependent logic
Usepkg/clock to control time rather than sleeping.
