Documentation
¶
Overview ¶
Example ¶
package main
import (
"fmt"
"slices"
"strings"
"testing"
"github.com/qawatake/fixify"
"github.com/qawatake/fixify/internal/example/model"
)
func main() {
// t is passed from the test function.
t := &testing.T{}
// specify how to connect models in a declarative way.
f := fixify.New(t,
Company().With(
Department("finance").With(
Employee(),
),
Department("sales"),
),
)
// Apply applies visitor function to each model and then call the connector functions.
f.Apply(func(v any) error {
switch v := v.(type) {
case *model.Company:
v.ID = 1
case *model.Department:
if v.Name == "finance" {
v.ID = 2
} else {
v.ID = 3
}
case *model.Employee:
v.ID = 4
}
return nil
})
allModels := f.All()
for _, company := range filter[*model.Company](allModels) {
fmt.Printf("CompanyID: %d\n", company.ID)
}
for _, department := range sortDepartments(filter[*model.Department](allModels)) {
fmt.Printf("DepartmentID: %d Name: %s CompanyID: %d\n", department.ID, department.Name, department.CompanyID)
}
for _, employee := range filter[*model.Employee](allModels) {
fmt.Printf("EmployeeID: %d DepartmentID: %d\n", employee.ID, employee.DepartmentID)
}
}
// Company represents a fixture for the company model.
func Company() *fixify.Model[model.Company] {
// Company is the root model, so it does not need a connector function.
return fixify.NewModel(new(model.Company))
}
// Department represents a fixture for the department model.
func Department(name string) *fixify.Model[model.Department] {
d := &model.Department{
Name: name,
}
return fixify.NewModel(d,
// specify how to connect a department to a company.
fixify.ConnectorFunc(func(_ testing.TB, department *model.Department, company *model.Company) {
department.CompanyID = company.ID
}),
)
}
// Employee represents a fixture for the employee model.
func Employee() *fixify.Model[model.Employee] {
return fixify.NewModel(new(model.Employee),
// specify how to connect an employee to a department.
fixify.ConnectorFunc(func(_ testing.TB, employee *model.Employee, department *model.Department) {
employee.DepartmentID = department.ID
}),
)
}
func filter[T any](models []any) []T {
filtered := make([]T, 0, len(models))
for _, v := range models {
if v, ok := v.(T); ok {
filtered = append(filtered, v)
}
}
return filtered
}
func sortDepartments(departments []*model.Department) []*model.Department {
slices.SortFunc(departments, func(a, b *model.Department) int {
return strings.Compare(a.Name, b.Name)
})
return departments
}
Output: CompanyID: 1 DepartmentID: 2 Name: finance CompanyID: 1 DepartmentID: 3 Name: sales CompanyID: 1 EmployeeID: 4 DepartmentID: 2
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Connecter ¶
type Connecter[T any] interface { // contains filtered or unexported methods }
Connector is an interface that incorporates the connector functions of the form func(t testing.TB, childModel *U, parentModel *V). It is used to establish connections between different model types. Use ConnectorFunc to get one.
func ConnectorFunc ¶
ConnectorFunc translates a function of the form func(t testing.TB, childModel *U, parentModel *V) into Connecter[U].
func ConnectorFuncWithLabel ¶
func ConnectorFuncWithLabel[U, V any, L comparable](label L, f func(t testing.TB, childModel *U, parentModel *V)) Connecter[U]
ConnectorFuncWithLabel translates a function of the form func(t testing.TB, childModel *U, parentModel *V) with a label into Connecter[U]. With different labels, you can connect the same parent model in different ways. See an example in Model.WithParentAs.
type Fixture ¶
type Fixture struct {
// contains filtered or unexported fields
}
Fixture collects models and resolves their dependencies.
func (*Fixture) All ¶
All returns all models in the fixture.
Example ¶
// t is passed from the test function.
t := &testing.T{}
f := fixify.New(t,
Company().With(
Department("finance").With(
Employee(),
),
Department("sales"),
),
)
// a model is either *model.Company, *model.Department, or *model.Employee.
models := f.All()
fmt.Println("Number of companies:", len(filter[*model.Company](models)))
fmt.Println("Number of departments:", len(filter[*model.Department](models)))
fmt.Println("Number of employees:", len(filter[*model.Employee](models)))
Output: Number of companies: 1 Number of departments: 2 Number of employees: 1
type IModel ¶
type IModel interface {
// contains filtered or unexported methods
}
IModel represents a set of models that can be connected to each other.
type Model ¶
type Model[T any] struct { // contains filtered or unexported fields }
Model is a wrapper model with ability to connect to other models. It implements IModel.
func NewModel ¶
NewModel is a constructor of Model.
Example ¶
package main
import (
"testing"
"github.com/qawatake/fixify"
"github.com/qawatake/fixify/internal/example/model"
)
func main() {
// t is passed from the test function.
t := &testing.T{}
fixify.New(t,
Book(),
)
}
// Book represents a fixture for the book model.
func Book() *fixify.Model[model.Book] {
return fixify.NewModel(
&model.Book{},
fixify.ConnectorFunc(func(_ testing.TB, book *model.Book, library *model.Library) {
book.LibraryID = library.ID
}),
)
}
func (*Model[T]) Bind ¶
Bind sets the pointer to the model. It is useful when you want to connect models to multiple parents.
Example ¶
package main
import (
"testing"
"github.com/qawatake/fixify"
"github.com/qawatake/fixify/internal/example/model"
)
func main() {
// t is passed from the test function.
t := &testing.T{}
var enrollment *fixify.Model[model.Enrollment]
fixify.New(t,
Student().With(
Enrollment().Bind(&enrollment),
),
Classroom().With(
enrollment,
),
)
}
func Student() *fixify.Model[model.Student] {
return fixify.NewModel(new(model.Student))
}
func Classroom() *fixify.Model[model.Classroom] {
return fixify.NewModel(new(model.Classroom))
}
func Enrollment() *fixify.Model[model.Enrollment] {
return fixify.NewModel(new(model.Enrollment),
fixify.ConnectorFunc(func(_ testing.TB, enrollment *model.Enrollment, student *model.Student) {
enrollment.StudentID = student.ID
}),
fixify.ConnectorFunc(func(_ testing.TB, enrollment *model.Enrollment, classroom *model.Classroom) {
enrollment.ClassroomID = classroom.ID
}),
)
}
func (*Model[T]) With ¶
With registers children models.
Example ¶
// Company, Department, and Employee are fixtures for the company, department, and employee models.
Company().With(
Department("finance").With(
Employee(),
Employee(),
),
Department("sales").With(
Employee(),
Employee(),
Employee(),
),
)
func (*Model[T]) WithParent ¶
WithParent registers a parent model.
func (*Model[T]) WithParentAs ¶
WithParentAs registers a parent model with a label.
Example ¶
package main
import (
"testing"
"github.com/qawatake/fixify"
"github.com/qawatake/fixify/internal/example/model"
)
func main() {
// t is passed from the test function.
t := &testing.T{}
fixify.New(t,
Follow().
WithParentAs("follower", User("bob")).
WithParentAs("followee", User("alice")),
)
}
func User(name string) *fixify.Model[model.User] {
return fixify.NewModel(&model.User{
Name: name,
})
}
func Follow() *fixify.Model[model.Follow] {
return fixify.NewModel(new(model.Follow),
fixify.ConnectorFuncWithLabel("follower", func(_ testing.TB, follow *model.Follow, follower *model.User) {
follow.FollowerID = follower.ID
}),
fixify.ConnectorFuncWithLabel("followee", func(_ testing.TB, follow *model.Follow, followee *model.User) {
follow.FolloweeID = followee.ID
}),
)
}