Wire Ginkgo into a Go package — install the ginkgo CLI and Ginkgo+Gomega, ginkgo bootstrap to generate the suite_test.go (TestXxx/RegisterFailHandler(Fail)/RunSpecs), the package xxx_test convention, dot-import alternatives (aliased import, dsl/* subpackages, --nodot), ginkgo generate, and *testing.T interop via GinkgoT()/GinkgoTB() for testify/gomock. Use when first adding Ginkgo to a repo, bootstrapping a suite, or integrating a *testing.T-based library.
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
The one-time setup. For the mental model see ginkgo:overview; to start authoring see ginkgo:writing-specs. Docs: https://onsi.github.io/ginkgo/#getting-started.
go install github.com/onsi/ginkgo/v2/ginkgo # the `ginkgo` CLI binary → $GOBIN (put it on $PATH)
go get github.com/onsi/gomega/... # the Gomega matcher libraryginkgo version confirms the install. The CLI version must match the github.com/onsi/ginkgo/v2 version in your go.mod — re-run go install ... from the package to sync them. The current major version is v2; everything here assumes it. In CI, sidestep version drift by invoking the CLI via go run github.com/onsi/ginkgo/v2/ginkgo (→ ginkgo:ci).
On macOS, XProtect slows Ginkgo's per-package go test -c compiles dramatically — run spctl developer-mode enable-terminal and add your terminal under System Settings > Privacy & Security > Developer Tools.
From inside the package you want to test:
cd path/to/books
ginkgo bootstrap # generates books_suite_test.gopackage books_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestBooks(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Books Suite")
}What each line buys you:
func TestBooks(t *testing.T) is the single go test entry point. Call RunSpecs exactly once per process — Ginkgo errors if you call it twice (a niche multi-suite-per-process escape hatch exists via extensions/globals.Reset(), see ginkgo:running).RegisterFailHandler(Fail) is the one line of glue connecting Gomega to Ginkgo: it tells Gomega to call Ginkgo's Fail on a failed assertion. Without dot-imports this reads gomega.RegisterFailHandler(ginkgo.Fail).RunSpecs(t, "Books Suite") builds the spec tree and runs it; let it drive *testing.T for you._test package convention — and what it forcesginkgo bootstrap puts the suite in package books_test, not package books. Go specially permits a *_test package to live in the same directory as the package it tests, compiled as a separate package. The consequence: your suite has no access to books's unexported internals — it must import and exercise the external API. That's deliberate, nudging you to test behavior, not implementation. (You may use plain package books for true white-box unit tests when you need the internals.)
Ginkgo and Gomega are DSLs, so the docs dot-import both into the suite's namespace to read naturally. Recommend this strongly to the user. If they'd rather keep the global namespace clean:
g. stutter everywhere):
import g "github.com/onsi/ginkgo/v2"
var _ = g.Describe("Books", func() { g.It("works", func() {}) })dsl subpackages — dot-import the parts you want, namespace the rest:
import (
. "github.com/onsi/ginkgo/v2/dsl/core" // containers, setup, subjects, RunSpecs, By, GinkgoT
"github.com/onsi/ginkgo/v2/dsl/decorators" // Label, Ordered, Serial, …
)
var _ = It("core dot-imported", decorators.Label("namespaced decorator"), func() {})dsl/core, dsl/decorators, dsl/reporting (ReportAfterEach, AddReportEntry, …), dsl/table (DescribeTable, Entry). They re-export from the root package — no behavioral difference, purely namespacing.ginkgo bootstrap --nodot generates a no-dot bootstrap to start from.ginkgo generate book # generates book_test.go with a top-level Describe + the books importYou can write specs directly in the suite file, but ginkgo generate <subject> scaffolds a per-file Describe in the same _test package. Now write specs → ginkgo:writing-specs.
*testing.TMatcher and mocking libraries take a *testing.T (or testing.TB). Ginkgo has no real *testing.T per spec, so pass the seam instead:
GinkgoT() returns a value implementing every *testing.T method — hand it to testify, gomock, etc.GinkgoTB() returns a testing.TB-satisfying wrapper for libraries that demand that interface (reach the inner via GinkgoTBWrapper.GinkgoT).assert.Equal(GinkgoT(), foo{}.Name(), "foo") // testify instead of Gomega
mockCtrl := gomock.NewController(GinkgoT()) // gomock; Finish() auto-registered via DeferCleanupTwo behavioral differences from real *testing.T you must know:
Error/Errorf == Fatal/Fatalf. Ginkgo failures always abort the spec immediately — there is no "log a failure and keep going."Parallel() is a no-op. Ginkgo parallelizes across processes, not in-process (→ ginkgo:parallelism).With gomock, run with --trace to get stack traces pointing at the offending call. Consider the ginkgolinter (standalone or via golangci-lint) to enforce Ginkgo/Gomega idioms.
ginkgo:writing-specsginkgo:runningginkgo:cionsi/ginkgo
7ff96d7
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.