.testspec.yaml — Spec Reference¶
Experimental
gen-cases and .testspec.yaml are experimental — an exploration of the approach. Schema, API, and behavior may change. Feedback welcome.
Alternatively, install the AI agent skills and let an AI generate cases directly from source code — no spec file required.
A .testspec.yaml file describes what to test in domain terms, without writing Go code. go-testgen gen-cases reads it and materializes the described cases into the tests slice of an existing _test.go.
Design Principle¶
The concrete values in
before,after, and checks are circumstantial — they depend on how the subject under test is built, what dependencies it has, and how injection works. The spec describes them in natural language. A generative AI translates them to Go code by reading the spec alongside the source and the generated_test.go.
A spec author works in the domain space (invariants, scenarios, business rules). An AI completes the implementation space (field names, mock patterns, exact literals).
Full Schema¶
version: "1" # required, always "1"
# ── Identification ────────────────────────────────────────────────────────────
package: <go package pattern> # required — e.g. ./connector/webhook
function: <FuncSpec> # required — e.g. WebhookNotifier.Deliver
test_file: <path> # optional — override target _test.go
# ── Test context ──────────────────────────────────────────────────────────────
context:
subject_init: <Go expression or description>
shared_setup: <description>
package_state:
- name: <identifier>
type: <Go type>
clear_between_cases: true | false
description: <what it captures>
# ── Fixtures ──────────────────────────────────────────────────────────────────
fixtures:
- name: <identifier>
type: <Go type>
description: <what it represents>
value: |
<Go literal — may be multiline>
# ── Check types ───────────────────────────────────────────────────────────────
check_types:
- id: <identifier used in cases>
type_name: <Go type name>
signature: <func signature>
composer: <composer function name>
package: <import path — omit if same package>
description: <what this type validates>
# ── Checks ────────────────────────────────────────────────────────────────────
checks:
- id: <function name>
for_type: <check_type id>
scope: global | local
signature: <full signature with return type>
when: <when to use this check>
params:
- name: <param name>
type: <Go type>
doc: <what this param represents>
sentinel_empty: <meaning of zero/empty value, if any>
captures: [<var1>, <var2>]
# ── Table fields ──────────────────────────────────────────────────────────────
table_fields:
- name: <field name>
type: <Go type>
role: input | gate | state
doc: <description>
# ── Cases ─────────────────────────────────────────────────────────────────────
cases:
- name: <test case name — appears in t.Run()>
description: <natural language scenario description>
fields:
<field_name>: <Go-syntax value>
before:
description: <what setup to perform>
mechanism: testify-mock | field-injection | field-reset | state-mutation | mixed | none
returns:
type: <Go return type>
used_as: <how the returned value is used>
after:
description: <what teardown to perform>
mechanism: stop-method | cancel-context | close-channel | mixed
checks:
- <check_id>(<args>)
gates:
<gate_field>: <value>
todo: false | true
Top-Level Fields¶
| Field | Required | Description |
|---|---|---|
version |
yes | Always "1". |
package |
yes | Go package pattern passed to go/packages. E.g. ./engine, ./connector/webhook. |
function |
yes | Receiver.Method or plain FuncName. Controls the TestXxx function name and target file derivation. |
test_file |
no | Explicit path to the _test.go to modify. Overrides automatic derivation. |
function format¶
| Value | Target test function | Derived filename |
|---|---|---|
Engine.Start |
TestEngine_Start |
engine_test.go |
WebhookNotifier.Deliver |
TestWebhookNotifier_Deliver |
webhook_notifier_test.go |
DummyNotifier.Exists |
TestDummyNotifier_Exists |
dummy_notifier_test.go |
NewEngine |
TestNewEngine |
engine_test.go |
ZH07i.Read |
TestZH07i_Read |
zh07i_test.go |
Receiver is converted to snake_case. For constructors (NewXxx), New is stripped before conversion.
Section Reference¶
| Section | Purpose |
|---|---|
context |
How the subject is constructed and what shared state the test body needs |
package_state |
Package-level variables used to capture side effects across test cases |
fixtures |
Shared data (payloads, constants) declared once before the test function |
check_types |
The closure-check function types used in this test |
checks |
Catalogue of assertion functions, with scope and parameter docs |
table_fields |
Extra columns in the test table beyond name, before, after, checks |
cases |
The test scenarios — the primary content of a spec |
before / after |
Setup and teardown patterns |