Composable, lazily-evaluated test fixtures for Go - inspired by pytest fixtures.
  • Go 92.1%
  • Just 7.9%
Attila Dudas d4700713b5
All checks were successful
ci/woodpecker/push/CI/3 Pipeline was successful
ci/woodpecker/push/CI/1 Pipeline was successful
ci/woodpecker/push/CI/2 Pipeline was successful
Add go report badge
2026-04-27 21:04:14 +02:00
.woodpecker Add CI (#1) 2026-04-27 21:00:47 +02:00
examples Move repo to codeberg 2026-04-27 13:49:07 +02:00
.gitignore Initial commit 2025-07-31 08:52:02 +02:00
CHANGELOG.md Make fix.New return a func instead of an interface 2025-10-02 09:38:53 +02:00
fixture.go Make fix.New return a func instead of an interface 2025-10-02 09:38:53 +02:00
fixture_test.go Move repo to codeberg 2026-04-27 13:49:07 +02:00
go.mod Move repo to codeberg 2026-04-27 13:49:07 +02:00
go.sum Initial commit 2025-07-31 08:52:02 +02:00
justfile Initial commit 2025-07-31 08:52:02 +02:00
LICENSE.md Move repo to codeberg 2026-04-27 13:49:07 +02:00
README.md Add go report badge 2026-04-27 21:04:14 +02:00
version_1_24.go Support go 1.25 2025-09-18 14:12:47 +02:00
version_1_25.go Support go 1.25 2025-09-18 14:12:47 +02:00
version_1_26.go Support go1.26 2026-03-10 13:32:45 +01:00

Go Report Card

fix

Composable, lazily-evaluated test fixtures for Go — inspired by pytest fixtures.

go get codeberg.org/datek/fix

Features

  • Evaluated once per test — a fixture called multiple times within the same *testing.T returns the cached value.
  • Composable — fixtures can depend on other fixtures; dependencies are resolved automatically.
  • Zero dependencies — only the Go standard library.

Usage

Define a fixture with fix.New, passing a function that receives *testing.T and returns a value. Call the fixture inside a test to get the value.

var fixtureDB = fix.New(func(t *testing.T) DB {
    t.Helper()
    return NewTestDB(t)
})

var fixtureUserStore = fix.New(func(t *testing.T) UserStore {
    t.Helper()
    db := fixtureDB(t) // resolved once, cached for this test
    return NewUserStore(db)
})

func TestCreateUser(t *testing.T) {
    store := fixtureUserStore(t)
    err := store.CreateUser("Alice")
    // ...
}

Because each fixture is only evaluated once per *testing.T, calling fixtureDB(t) from multiple fixtures within the same test always returns the same instance — no accidental duplication of shared resources.

Dependency resolution

Fixtures can freely call other fixtures. The dependency graph is resolved lazily at test time:

var fixtureStatements = fix.New(func(t *testing.T) *[]string {
    return &[]string{}
})

var fixtureMockDB = fix.New(func(t *testing.T) DB {
    statements := fixtureStatements(t)
    return NewMockDB(func(stmt string) error {
        *statements = append(*statements, stmt)
        return nil
    })
})

var fixtureUserStore = fix.New(func(t *testing.T) UserStore {
    return NewUserStore(fixtureMockDB(t))
})

All three fixtures share the same statements slice within a single test, making assertions straightforward.

Examples

A full working example (mock DB + user store) lives in the examples/ directory. Core behaviour is covered in fixture_test.go.

Requirements

Go 1.24 or later.