https://github.com/mhiro2/seedling
Dependency-aware test data builder for Go that resolves foreign-key DB relationships automatically.
https://github.com/mhiro2/seedling
database fixtures go gorm pgx sql sqlc testing
Last synced: 23 days ago
JSON representation
Dependency-aware test data builder for Go that resolves foreign-key DB relationships automatically.
- Host: GitHub
- URL: https://github.com/mhiro2/seedling
- Owner: mhiro2
- License: mit
- Created: 2026-03-16T12:02:21.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-03-28T13:14:35.000Z (about 1 month ago)
- Last Synced: 2026-03-28T17:11:47.087Z (about 1 month ago)
- Topics: database, fixtures, go, gorm, pgx, sql, sqlc, testing
- Language: Go
- Homepage:
- Size: 646 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
seedling
Dependency-aware test data builder for Go and SQL databases.
seedling lets tests create only the rows they need while automatically resolving foreign-key dependencies in the correct order. You provide the insert logic. seedling handles planning, FK assignment, and execution order.
---
## âĻ Why seedling?
Manually wiring FK dependencies across 4 tables:
```go
func TestCreateTask(t *testing.T) {
company, err := db.InsertCompany(ctx, InsertCompanyParams{Name: "acme"})
if err != nil { t.Fatal(err) }
user, err := db.InsertUser(ctx, InsertUserParams{
Name: "alice", CompanyID: company.ID,
})
if err != nil { t.Fatal(err) }
project, err := db.InsertProject(ctx, InsertProjectParams{
Name: "renewal", CompanyID: company.ID,
})
if err != nil { t.Fatal(err) }
task, err := db.InsertTask(ctx, InsertTaskParams{
Title: "design", ProjectID: project.ID, AssigneeUserID: user.ID,
})
if err != nil { t.Fatal(err) }
_ = task
}
```
With seedling, the graph is resolved automatically:
```go
func TestCreateTask(t *testing.T) {
result := seedling.InsertOne[Task](t, db)
task := result.Root()
_ = task
}
```
seedling handles FK ordering, graph expansion, and cleanup so your tests stay focused on what matters:
- ðŠķ Zero runtime dependencies in the core module; optional DB helpers live in companion packages
- ð Automatic FK resolution with topological insert ordering
- ðŋ Minimal graph expansion: only required ancestors are inserted
- ð§ Type-safe per-test overrides with `Set`, `Use`, `Ref`, `With`, `When`, and `Only`
- âŧïļ `WithTx` and companion helpers for auto-rollback transactions -- no manual cleanup
- ð Works with sqlc, `database/sql`, pgx, GORM, or any other DB handle you own
- ð Supports `HasMany`, `ManyToMany`, composite keys, cleanup, dry runs, and insert logging
- ðē Includes deterministic fake data via [`seedling/faker`](https://pkg.go.dev/github.com/mhiro2/seedling/faker) with multi-locale support (en, ja, zh, ko, de, fr)
## ðĶ Installation
Add an import in your code, then let the toolchain record the dependency:
```go
import "github.com/mhiro2/seedling"
```
Use the same pattern for companion packages when you need them, for example [`seedling/faker`](https://pkg.go.dev/github.com/mhiro2/seedling/faker) (`github.com/mhiro2/seedling/faker`) or [`seedlingpgx`](https://pkg.go.dev/github.com/mhiro2/seedling/seedlingpgx) (`github.com/mhiro2/seedling/seedlingpgx`).
Install the `seedling-gen` CLI (pick one):
```bash
# Homebrew (macOS / Linux) â [third-party tap](https://github.com/mhiro2/homebrew-tap)
brew install --cask mhiro2/tap/seedling-gen
```
```bash
# Go toolchain
go install github.com/mhiro2/seedling/cmd/seedling-gen@latest
```
## ð Quick Start
1. **Generate blueprints from your schema**
```bash
# From SQL DDL
seedling-gen sql --pkg testutil --out blueprints.go schema.sql
# Or from other sources:
seedling-gen sqlc --config sqlc.yaml --pkg testutil --out blueprints.go
seedling-gen gorm --dir ./models --import-path github.com/you/app/models --pkg testutil
seedling-gen ent --dir ./ent/schema --import-path github.com/you/app/ent --pkg testutil
seedling-gen atlas --pkg testutil schema.hcl
seedling-gen sql --explain schema.sql
```
This generates struct types, `RegisterBlueprints()`, relations, and Insert stubs. Fill in the `// TODO` callbacks with your DB logic:
```go
Insert: func(ctx context.Context, db seedling.DBTX, v Company) (Company, error) {
return insertCompany(ctx, db, v) // your DB call
},
```
The snippets below assume the generated package is named `testutil`.
For a runnable minimal version of this flow, see [examples/quickstart](./examples/quickstart).
2. **Use it in tests**
```go
func TestUser(t *testing.T) {
seedling.ResetRegistry()
testutil.RegisterBlueprints()
result := seedling.InsertOne[testutil.User](t, db)
user := result.Root()
if user.ID == 0 {
t.Fatal("expected user ID to be set")
}
if user.CompanyID == 0 {
t.Fatal("expected company to be inserted automatically")
}
}
```
3. **Override only what the test cares about**
```go
func TestNamedUser(t *testing.T) {
seedling.ResetRegistry()
testutil.RegisterBlueprints()
company := seedling.InsertOne[testutil.Company](t, db).Root()
result := seedling.InsertOne[testutil.User](t, db,
seedling.Set("Name", "alice"),
seedling.Use("company", company),
)
user := result.Root()
_ = user
}
func TestTaskProject(t *testing.T) {
seedling.ResetRegistry()
testutil.RegisterBlueprints()
// Only("project") inserts task + project subtree only,
// skipping the assignee relation entirely.
result := seedling.InsertOne[testutil.Task](t, db,
seedling.Only("project"),
)
_ = result
}
```
When you want automatic rollback with `database/sql`, use `seedling.WithTx(t, db)`.
For a runnable transaction-focused example, see [examples/with-tx](./examples/with-tx).
For a runnable batch-oriented example, see [examples/batch-insert](./examples/batch-insert).
## âïļ Comparison
| Tool | Main model | Strong at | Not designed for |
| --- | --- | --- | --- |
| seedling | Dependency-aware builders with DB callbacks | Per-test graph generation, automatic FK resolution, type-safe overrides, graph inspection, codegen | Bulk loading large static fixture files |
| [eyo-chen/gofacto](https://github.com/eyo-chen/gofacto) | Generic factory with explicit FK associations | Ergonomic zero-config field filling, `WithOne`/`WithMany` associations, multi-DB support | Automatic graph resolution, minimal graph expansion |
| [go-testfixtures/testfixtures](https://github.com/go-testfixtures/testfixtures) | Fixture files loaded into DB | Stable predefined datasets for integration tests | Relation-aware per-test graph construction |
| [bluele/factory-go](https://github.com/bluele/factory-go) | In-memory object factories | Flexible object construction and traits-like composition | Planning SQL insert order across FK graphs |
| [brianvoe/gofakeit](https://github.com/brianvoe/gofakeit) | Fake data generator | Realistic random values | Database insertion orchestration or relation expansion |
## ð Examples
- [basic](./examples/basic): register blueprints and insert rows with automatic parent creation
- [quickstart](./examples/quickstart): generated-style `RegisterBlueprints()` flow that matches the README Quick Start
- [custom-defaults](./examples/custom-defaults): customize values with `Set`, `With`, and `Generate`
- [reuse-parent](./examples/reuse-parent): reuse existing rows with `Use`
- [batch-insert](./examples/batch-insert): batch inserts with shared `Ref` dependencies and per-row `SeqRef` overrides
- [with-tx](./examples/with-tx): `database/sql` transaction helper with `seedling.WithTx`
- [sqlc](./examples/sqlc): wire blueprints to sqlc-generated query code
- pgx transactions: use `github.com/mhiro2/seedling/seedlingpgx` with `pgxpool.Pool` or `*pgx.Conn`
- GORM / ent / Atlas: use `seedling-gen` with `-gorm`, `-ent`, or `-atlas` flags to generate blueprints from your existing schema definitions
## ð Learn More
- [Guide](./docs/guide.md) -- workflows, option reference, and integration patterns
- [Architecture](./ARCHITECTURE.md) -- internal pipeline design (planner, graph, executor)
- [Agent Skill: seedling-gen CLI](./skills/seedling-gen-cli/SKILL.md) -- instructions for AI agents that need to choose the right generator mode and scaffold blueprints
- [Agent Skill: seedling test setup](./skills/seedling-test-setup/SKILL.md) -- instructions for AI agents that write Go tests using seedling blueprints
- [pkg.go.dev API reference](https://pkg.go.dev/github.com/mhiro2/seedling) -- full type and function docs
## ð License
MIT