CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/go-unit-tests

Go unit testing with the stdlib `testing` package - `func TestXxx(t *testing.T)` convention, the table-driven idiom with `t.Run` subtests, `t.Parallel()`, benchmarks (`BenchmarkXxx` + benchstat), examples (`ExampleXxx`), native fuzzing (`FuzzXxx`, Go 1.18+), coverage (`-cover` / `-coverprofile` + threshold gating), build tags, `t.Helper()` / `t.Cleanup`, and `-race` CI. Includes framework choice (stdlib `testing` is the idiomatic default; Ginkgo BDD for Kubernetes-ecosystem projects via references) and test-authoring conventions (framework detection from go.sum + existing suite files, `_test.go` placement, `t.Errorf` vs `t.Fatalf`). References cover Ginkgo + Gomega and Go mocking (gomock, testify/mock). Use for any Go unit-test task: writing table-driven tests, benchmarks, fuzz targets, coverage gates, or CI wiring.

72

Quality

91%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

ginkgo.mdreferences/

Ginkgo + Gomega - Go BDD testing (reference)

Companion reference for go-unit-tests. Consult for Kubernetes-ecosystem projects (the community convention) or teams with a BDD culture (rspec/mocha background). For non-BDD Go projects, stdlib testing (SKILL.md) is the idiomatic choice.

Per onsi.github.io/ginkgo:

Install and bootstrap

go install github.com/onsi/ginkgo/v2/ginkgo@latest
go get github.com/onsi/ginkgo/v2
go get github.com/onsi/gomega/...

ginkgo bootstrap         # creates <package>_suite_test.go
ginkgo generate calc     # creates calc_test.go template

The bootstrap file registers the suite:

package calc_test

import (
    "testing"

    . "github.com/onsi/ginkgo/v2"
    . "github.com/onsi/gomega"
)

func TestCalc(t *testing.T) {
    RegisterFailHandler(Fail)
    RunSpecs(t, "Calc Suite")
}

Spec structure

var _ = Describe("Calculator", func() {
    var c *calc.Calculator

    BeforeEach(func() {
        c = calc.New()
    })

    Describe("Add", func() {
        Context("with positive numbers", func() {
            It("adds correctly", func() {
                Expect(c.Add(1, 2)).To(Equal(3))
            })
        })

        Context("with overflow", func() {
            It("returns error", func() {
                _, err := c.AddSafe(math.MaxInt, 1)
                Expect(err).To(HaveOccurred())
            })
        })
    })
})

var _ = Describe(...) registers the spec at package init time. Hooks (BeforeSuite / AfterSuite, BeforeEach / AfterEach, JustBeforeEach / JustAfterEach) nest with Describe/Context - inner BeforeEach runs in addition to outer ones (gn-docs).

An It block with no Gomega Expect passes silently - always assert.

Gomega matchers

Per onsi.github.io/gomega - Expect(actual).To(matcher) and Expect(actual).NotTo(matcher):

Expect(value).To(Equal(expected))           // reflect.DeepEqual semantics
Expect(value).To(BeNil())
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError("expected message"))
Expect(str).To(ContainSubstring("substring"))
Expect(str).To(MatchRegexp(`\d+`))
Expect(list).To(HaveLen(3))
Expect(list).To(ContainElement("alice"))
Expect(list).To(ConsistOf("alice", "bob"))  // unordered
Expect(value).To(BeNumerically(">", 0))
Expect(value).To(BeNumerically("~", 3.14, 0.01))  // tolerance
Expect(action).To(Panic())
Expect(channel).To(Receive(&value))

Async polling - Eventually polls until the condition holds; Consistently verifies it stays true (use instead of sleep-based polls):

Eventually(func() bool { return ready() }).Should(BeTrue())
Consistently(func() bool { return stable() }).Should(BeTrue())

DescribeTable + Entry (parametrize)

DescribeTable("Add",
    func(a, b, expected int) {
        Expect(calc.Add(a, b)).To(Equal(expected))
    },
    Entry("positive", 1, 2, 3),
    Entry("zero", 0, 0, 0),
    Entry("negative", -1, 1, 0),
)

Focus, skip, parallel

FDescribe / FIt focus (only those run); PDescribe / PIt skip. Parallel: ginkgo -p ./... (CPU count) or -procs=4 - per-process, so tests must be independent.

CI integration

- run: go install github.com/onsi/ginkgo/v2/ginkgo@latest
- run: ginkgo -p --cover --coverprofile=coverage.out --no-focus -r
- uses: codecov/codecov-action@v4
  with: { files: coverage.out }

--no-focus fails the build if any F-prefix specs exist (catches debug-leftover focus). JUnit XML: ginkgo --junit-report=junit.xml -r.

Anti-patterns

Anti-patternWhy it failsFix
Ginkgo for a non-BDD codebaseVerbose vs stdlib testingstdlib (SKILL.md)
Committed FDescribe / FItSuite runs only focused specs--no-focus in CI
Sleep-based async assertionsFlakyEventually / Consistently
Heavy nesting (5+ levels)Setup hard to reason aboutFlatten with Describe+It

References

  • gn-docs - Ginkgo documentation
  • gomega - Gomega matchers reference
  • github.com/onsi/ginkgo - repository

SKILL.md

tile.json