| name | setup |
| description | 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. |
Wiring Ginkgo into a suite
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.
1. Install the CLI and the libraries
go install github.com/onsi/ginkgo/v2/ginkgo
go get github.com/onsi/gomega/...
ginkgo 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.
2. Bootstrap the suite
From inside the package you want to test:
cd path/to/books
ginkgo bootstrap
package 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.
3. The _test package convention — and what it forces
ginkgo 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.)
4. Dot-imports and the alternatives
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:
- Alias the whole DSL (slight
g. stutter everywhere):
import g "github.com/onsi/ginkgo/v2"
var _ = g.Describe("Books", func() { g.It("works", func() {}) })
- Mix-and-match the
dsl subpackages — dot-import the parts you want, namespace the rest:
import (
. "github.com/onsi/ginkgo/v2/dsl/core"
"github.com/onsi/ginkgo/v2/dsl/decorators"
)
var _ = It("core dot-imported", decorators.Label("namespaced decorator"), func() {})
Available: 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.
5. Add spec files
ginkgo generate book
You 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.
6. Third-party libraries that want a *testing.T
Matcher 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")
mockCtrl := gomock.NewController(GinkgoT())
Two 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.
Where to go next
- Authoring specs (containers, subjects, setup/cleanup, construction-time pitfalls) →
ginkgo:writing-specs
- The CLI surface (run, watch, build, randomization, multiple suites) →
ginkgo:running
- A recommended CI configuration →
ginkgo:ci