GithubHelp home page GithubHelp logo

bluele / factory-go Goto Github PK

View Code? Open in Web Editor NEW
363.0 10.0 21.0 38 KB

A library for setting up Golang objects inspired by factory_bot.

License: MIT License

Go 100.00%
go golang factory-girl factory-boy fixtures-replacement

factory-go's People

Contributors

38tter avatar bluele avatar cforbes avatar ismith avatar jfo84 avatar noahgoldman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

factory-go's Issues

Persistent models example?

Thanks for the great project!
How do i make a side effect for the model initialization (i need to store it in the database)?

make email more random

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.

No support for nested atributes within the MustCreateWithOption

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.

Allow option for nested values on slice fields

Intro

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.

Example

Context

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),
)

Proposal:

My proposal would work like this:

Scenario 1: Dot notation for nested array fields

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

Scenario 2: Dot notation for nested array fields on specific index in slice subfactory bounds

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

Scenario 3: Dot notation for nested array fields on specific index out of slice subfactory bounds

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.

SeqInt() access to context obj

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.

NewFactory working in order of struct instead of factory

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.

Allow parent to be passed into create methods

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!

EmbeddedType not supported?

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.

...

Each group of tests should have its own fixtures so we do not need to make modifications to other tests test data

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.