Help us shape the future of Go! Take the 2026 Go Developer Survey

factory

package
v0.30.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package factory builds models with fake data for tests and seeders:

var Users = factory.New(func(f *factory.Faker) models.User {
	return models.User{Name: f.Name(), Email: f.Email()}
})

admins, err := Users.Count(3).State(func(u *models.User) { u.Role = "admin" }).Create(ctx, db)

Factories are values: State, Count, Seed and AfterCreate return copies, so a base factory can be shared. Make builds values in memory; Create also inserts them through orm.Create, CreateMany in batches through orm.CreateMany. A Faker seeded per factory makes the data reproducible (Seed), which seeders and golden tests rely on.

See https://github.com/AlexGalhardo/vukem/blob/main/docs/database.md#factories-and-seeders.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Pick

func Pick[T any](f *Faker, items ...T) T

Pick returns one of items.

Types

type Factory

type Factory[T any] struct {
	// contains filtered or unexported fields
}

Factory builds T values.

func New

func New[T any](def func(f *Faker) T) Factory[T]

New returns a factory whose definition returns one model with fake data.

func (Factory[T]) AfterCreate

func (f Factory[T]) AfterCreate(fn func(ctx context.Context, ex database.Executor, m *T) error) Factory[T]

AfterCreate runs fn for every created model, inside Create; use it to create related models:

Users.AfterCreate(func(ctx context.Context, ex database.Executor, u *User) error {
	_, err := Posts.Count(2).State(func(p *Post) { p.UserID = u.ID }).Create(ctx, ex)
	return err
})

func (Factory[T]) Count

func (f Factory[T]) Count(n int) Factory[T]

Count sets how many models Make and Create build.

func (Factory[T]) Create

func (f Factory[T]) Create(ctx context.Context, ex database.Executor) ([]T, error)

Create builds and inserts Count models (in a transaction when ex is a *database.DB), then runs AfterCreate hooks.

Example
package main

import (
	"context"
	"fmt"

	"github.com/AlexGalhardo/vukem/database"
	"github.com/AlexGalhardo/vukem/factory"
	"github.com/AlexGalhardo/vukem/orm"
)

type User struct {
	orm.Model
	Name string
	Role string
}

func main() {
	ctx := context.Background()

	db, _ := database.Open(ctx, ":memory:")
	defer db.Close()

	_, _ = db.ExecContext(ctx, `CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT,
		created_at TIMESTAMP, updated_at TIMESTAMP, name TEXT, role TEXT)`)

	users := factory.New(func(f *factory.Faker) User {
		return User{Name: f.Name(), Role: "member"}
	})

	created, err := users.Count(3).Create(ctx, db)
	if err != nil {
		fmt.Println(err)
		return
	}

	n, _ := orm.QueryOf[User](db).Count(ctx)
	fmt.Println(len(created), n, created[0].ID > 0)
}
Output:
3 3 true

func (Factory[T]) CreateMany added in v0.27.0

func (f Factory[T]) CreateMany(ctx context.Context, ex database.Executor) ([]T, error)

CreateMany builds Count models and inserts them with orm.CreateMany: multi-row INSERTs split under the dialect's bound-parameter limit, with the generated ids written back (RETURNING on PostgreSQL and SQLite, one INSERT per row on MySQL). AfterCreate hooks run once every row is stored, in order, inside the same transaction.

Given a *database.DB, CreateMany opens that transaction and an insert or hook error rolls back every row. Given a *database.Tx it joins it: the error is returned and the caller owns the rollback (db.Tx rolls back when its function returns the error).

Prefer it to Create for seeding many rows; Create inserts one row at a time and runs each model's hooks right after its insert.

func (Factory[T]) CreateOne

func (f Factory[T]) CreateOne(ctx context.Context, ex database.Executor) (T, error)

CreateOne builds and inserts one model.

func (Factory[T]) Locale added in v0.27.0

func (f Factory[T]) Locale(l Locale) Factory[T]

Locale makes the definition's Faker generate data in l:

Products.Locale(factory.LocalePTBR()).Seed(42).Count(100).Make()

func (Factory[T]) Make

func (f Factory[T]) Make() []T

Make builds Count models without saving them.

Example
package main

import (
	"fmt"

	"github.com/AlexGalhardo/vukem/factory"
	"github.com/AlexGalhardo/vukem/orm"
)

type User struct {
	orm.Model
	Name string
	Role string
}

func main() {
	users := factory.New(func(f *factory.Faker) User {
		return User{Name: f.Name(), Role: "member"}
	})

	admins := users.Count(2).State(func(u *User) { u.Role = "admin" }).Make()
	for _, u := range admins {
		fmt.Println(u.Role, u.Name != "")
	}
}
Output:
admin true
admin true

func (Factory[T]) MakeOne

func (f Factory[T]) MakeOne() T

MakeOne builds one model without saving it.

func (Factory[T]) Seed

func (f Factory[T]) Seed(seed uint64) Factory[T]

Seed makes the fake data reproducible.

func (Factory[T]) State

func (f Factory[T]) State(fn func(*T)) Factory[T]

State applies fn to every built model, after the definition (and after earlier states).

type Faker

type Faker struct {
	// contains filtered or unexported fields
}

Faker generates fake data. It is deterministic for a given seed; it is not cryptographically secure and must never produce secrets.

func NewFaker

func NewFaker(seed uint64) *Faker

NewFaker returns a Faker seeded with seed, with the zero Locale (the original data set; see Locale). Choose a locale with WithLocale:

f := factory.NewFaker(42).WithLocale(factory.LocalePTBR())

func (*Faker) Address added in v0.27.0

func (f *Faker) Address() string

Address returns a one-line postal address whose city and state match.

func (*Faker) Bool

func (f *Faker) Bool() bool

Bool returns true or false.

func (*Faker) Category added in v0.27.0

func (f *Faker) Category() string

Category returns a store category ("Home & Kitchen", "Casa e Cozinha").

func (*Faker) City added in v0.27.0

func (f *Faker) City() string

City returns a city name.

func (*Faker) Company added in v0.27.0

func (f *Faker) Company() string

Company returns a company name ("Baker Logistics LLC", "Silva & Costa Comércio Ltda").

func (*Faker) Email

func (f *Faker) Email() string

Email returns an address on a reserved example domain, unique within one Make and unlikely to collide across Makes.

func (*Faker) EmailFor added in v0.27.0

func (f *Faker) EmailFor(name string) string

EmailFor returns an address on a reserved example domain whose local part is derived from name ("Ana Luíza" gives ana.luiza.…), unique within one Make like Email.

func (*Faker) FakeCPF added in v0.27.0

func (f *Faker) FakeCPF() string

FakeCPF returns a string in the Brazilian CPF format ("123.456.789-09") whose first check digit is always wrong: it can never be a real person's CPF, and every standard CPF validator rejects it. Seed CPF columns directly; do not send it through validation meant for real documents.

func (*Faker) FirstName

func (f *Faker) FirstName() string

FirstName returns a first name.

func (*Faker) Float

func (f *Faker) Float(lo, hi float64) float64

Float returns a number in [lo, hi).

func (*Faker) Int

func (f *Faker) Int(lo, hi int) int

Int returns a number in [lo, hi].

func (*Faker) LastName

func (f *Faker) LastName() string

LastName returns a last name.

func (*Faker) Locale added in v0.27.0

func (f *Faker) Locale() Locale

Locale returns the Faker's locale.

func (*Faker) Name

func (f *Faker) Name() string

Name returns a full name.

func (*Faker) Paragraph

func (f *Faker) Paragraph() string

Paragraph returns 3–6 sentences.

func (*Faker) PostalCode added in v0.27.0

func (f *Faker) PostalCode() string

PostalCode returns a ZIP code (en) or a CEP (pt-BR, "01310-100").

func (*Faker) ProductDescription added in v0.27.0

func (f *Faker) ProductDescription() string

ProductDescription returns a one-line product description built on ProductTitle.

func (*Faker) ProductTitle added in v0.27.0

func (f *Faker) ProductTitle() string

ProductTitle returns a product title for a listing ("Rustic Oak Desk", "Cadeira Ergonômica de Aço").

func (*Faker) Sentence

func (f *Faker) Sentence() string

Sentence returns a capitalized sentence of 6–12 words.

func (*Faker) Seq

func (f *Faker) Seq() int

Seq is the 1-based index of the model being built (unique per Make).

func (*Faker) Slug

func (f *Faker) Slug() string

Slug returns a lowercase, dash-separated ASCII slug of 3 words.

func (*Faker) State added in v0.27.0

func (f *Faker) State() string

State returns a state code ("IL", "SP"), independent of City; Address keeps the two consistent.

func (*Faker) StreetAddress added in v0.27.0

func (f *Faker) StreetAddress() string

StreetAddress returns a street and number ("742 Maple Ave", "Rua das Flores, 120").

func (*Faker) Time

func (f *Faker) Time(from, to time.Time) time.Time

Time returns a time between from and to.

func (*Faker) URL

func (f *Faker) URL() string

URL returns an https URL on an example domain.

func (*Faker) UUID

func (f *Faker) UUID() string

UUID returns a random version 4 UUID (not for secrets).

func (*Faker) Username

func (f *Faker) Username() string

Username returns a lowercase handle, unique within one Make.

func (*Faker) WithLocale added in v0.27.0

func (f *Faker) WithLocale(l Locale) *Faker

WithLocale makes f generate names, words, companies, products and addresses in l, and returns f. It consumes no randomness, so the output stays reproducible for the seed.

Example
package main

import (
	"fmt"

	"github.com/AlexGalhardo/vukem/factory"
)

func main() {
	f := factory.NewFaker(2026).WithLocale(factory.LocalePTBR())

	fmt.Println(f.Name())
	fmt.Println(f.ProductTitle())
	fmt.Println(f.Category())
	fmt.Println(f.Address())
}
Output:
Arthur Dias
Mochila Rústica de Cerâmica
Beleza
Avenida Getúlio Vargas, 748 - Manaus/AM, 37267-205

func (*Faker) Word

func (f *Faker) Word() string

Word returns a word in the Faker's locale (lorem ipsum for the zero Locale).

func (*Faker) Words

func (f *Faker) Words(n int) string

Words returns n words separated by spaces.

type Locale added in v0.27.0

type Locale struct {
	// contains filtered or unexported fields
}

Locale selects the language and country of the data a Faker generates.

The zero Locale is not English: it is the original data set (a mixed list of mostly Brazilian first names, lorem ipsum words), kept so that NewFaker(seed) and Factory.Seed(n) produce the same rows they did before locales existed. Only the methods that data set never had (Company, ProductTitle, ProductDescription, Category and the address methods) use English data there. Pass LocaleEN or LocalePTBR for one consistent language.

func LocaleEN added in v0.27.0

func LocaleEN() Locale

LocaleEN returns the English (United States) locale.

func LocalePTBR added in v0.27.0

func LocalePTBR() Locale

LocalePTBR returns the Brazilian Portuguese locale.

func (Locale) Name added in v0.27.0

func (l Locale) Name() string

Name is the locale's BCP 47 tag ("en", "pt-BR"), or "" for the zero Locale.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL