bluele / factory-go Goto Github PK
View Code? Open in Web Editor NEWA library for setting up Golang objects inspired by factory_bot.
License: MIT License
A library for setting up Golang objects inspired by factory_bot.
License: MIT License
as it is in in factorygirl, would be very useful if factory-fo support setting options for related objects (separated by dot):
user := factory.UserFactory.MustCreateWithOption(map[string]interface{}{"Role.RoleId": 2})
Thanks for the great project!
How do i make a side effect for the model initialization (i need to store it in the database)?
Each group of tests should have its own fixtures so we do not need to make modifications to other tests test data
I have a struct like below
type Model struct {
ID uuid.UUID
}
type User struct {
Model
Name string
}
and I am trying to do something like this
var UserFactory = factory.NewFactory(&models.User{}).
Attr("ID", func(args factory.Args) (interface{}, error) {
id := uuid.NewV4()
return id, nil
})
and I got this No such attribute name: ID
, I don't have idea how to resolve this.
This is sample code.
type User struct {
Fullname string
Firstname string
Lastname string
}
var UserFactory = factory.NewFactory(
&User{},
).Attr("Firstname", func(args factory.Args) (interface{}, error) {
return "John", nil
}).Attr("Lastname", func(args factory.Args) (interface{}, error) {
return "Doe", nil
}).Attr("Fullname", func(args factory.Args) (interface{}, error) {
user := args.Instance().(*User)
return fmt.Sprintf("%v %v", user.Firstname, user.Lastname), nil
})
user := UserFactory.MustCreate().(*User)
fmt.Println("Fullname:", user.Fullname, " Firstname:", user.Firstname, " Lastname:", user.Lastname)
Expect: Fullname: John Doe Firstname: John Lastname: Doe
Actual : Fullname: Firstname: John Lastname: Doe
I think when this work in order that define in struct. It generate Fullname
first. In that time, Firstname
and Lastname
is not generated yet. So, Fullname
is empty.
As part of the usage to calls like SeqInt(...)
and SeqString(...)
is it possible to get access to the args.Context()
at all?
I want to pass in data that I need to the use as part of these builders.
This is not clear enough from current documentation
First off just want to say thanks, this project has been super helpful to me as I've been testing a DB backed application that features a complex graph of related models.
One feature that would be very helpful is if I could pass an explicit parent into a factory create method. This would let me use a factory as both a subfactory in a chain of related factories and in isolation to create a new instance of a model to add to an existing chain of related models.
Let me know what you think!
I'm currently using this package for test fixture generation
and it happens quite often that i get the same email in just few repetitive calls, which prevents from using it 'as is' and requiring to add some random part manually.
Hi!
For some time we have been using this library at my company, and the dot notation for nested field setting on subfactories has proven really useful. It make really the declaration of new instances with fixed data really elegant.
Now, I think a similar strategy could be carried over for slice nested fields.
If you like the idea, I could PR it myself.
For example (borrowed from our codebase):
type Player struct {
ID string
FirstName string
LastName string
ExternalIds []ExternalID
}
type ExternalID struct {
ID string
Provider string
}
our factories look like:
func playerFactoryBuilder(model any) *factory.Factory {
return factory.NewFactory(
model,
).Attr(
"ID",
AlphanumericGenerator(10),
).Attr(
"FirstName", FirstNameGenerator,
).Attr(
"LastName", LastNameGenerator,
).SubSliceFactory(
"ExternalIds",
externalIDFactory,
func() int { return 2 },
)
}
var externalIDFactory = NewFactory(
models.ExternalID{},
).Attr(
"Provider",
ConstantGenerator("somewhat"),
).Attr(
"ID",
AlphanumericGenerator(10),
)
My proposal would work like this:
func main() {
for i := 0; i < 3; i++ {
player := PlayerFactory.MustCreateWithOption(map[string]any{"ExternalIds.Provider": "some-provider"}).(*Player)
for i, _ := range player.externalIds {
fmt.Println("ID:", player.ExternalIds.[i].ID, " Provider:", player.ExternalIds[i].Provider)
}
}
}
would affect all slice generated instances, printing something like
ID: 12ad23d4bn Provider: some-provider
ID: 32ad23d4bn Provider: some-provider
func main() {
for i := 0; i < 3; i++ {
player := PlayerFactory.MustCreateWithOption(map[string]any{"ExternalIds.1.Provider": "some-provider"}).(*Player)
for i, _ := range player.externalIds {
fmt.Println("ID:", player.ExternalIds.[i].ID, " Provider:", player.ExternalIds[i].Provider)
}
}
}
would affect only the instance generated at the specified index, printing something like
ID: 12ad23d4bn Provider: somewhat
ID: 32ad23d4bn Provider: some-provider
func main() {
for i := 0; i < 3; i++ {
player := PlayerFactory.MustCreateWithOption(map[string]any{"ExternalIds.2.Provider": "some-provider"}).(*Player)
for i, _ := range player.externalIds {
fmt.Println("ID:", player.ExternalIds.[i].ID, " Provider:", player.ExternalIds[i].Provider)
}
}
}
would panic with an error.
It would be really useful to provide options for nested attributes in subfactories.
For example, I propose the dot .
as a delimiter for attributes nesting. Following with the subfactory example, we should be able to declare a user with a specific name for its group:
func main() {
for i := 0; i < 3; i++ {
user := UserFactory.MustCreateWithOption(map[string]any{"Group.Name": "group-x"}).(*User)
fmt.Println(
"ID:", user.ID, " Name:", user.Name, " Location:", user.Location,
" Group.ID:", user.Group.ID, " Group.Name", user.Group.Name)
}
}
Output
ID: 1 Name: user-1 Location: Tokyo Group.ID: 1 Group.Name group-x
ID: 2 Name: user-2 Location: Tokyo Group.ID: 2 Group.Name group-x
ID: 3 Name: user-3 Location: Tokyo Group.ID: 1 Group.Name group-x
This is already implemented on other libraries, for example within Model Bakery. At draftea we are extensibely using factory-go, so I would be excited to have this built in.
We could carry out the job, but first I wan't to be sure you also think this is a good idea and is in tune with you long-term aspirations for the project.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.