Forgery v0.1.0 Forgery behaviour View Source
Forgery is a slim though extensible test data generator in Elixir.
Forgery provides a few simple APIs to work with. To get started, you
need to implement the make/2 callback:
defmodule MyUser do
defstruct [:id, :username, :password]
end
defmodule MyFactory do
use Forgery
def make(:user, fields) do
fields
|> put_new_field(:id, make_unique_integer())
|> put_new_field(:username, "user" <> to_string(make_unique_integer()))
|> create_struct(MyUser)
end
end
iex> import MyFactory
iex>
iex> %MyUser{} = make(:user)
iex> %MyUser{id: 42} = make(:user, id: 42)
iex> [%MyUser{}, %MyUser{}] = make_many(:user, 2)
And just as simple as that!
Ecto integration
Forgery was built with easy Ecto integration in mind, though not limiting to it.
For example if you use Ecto and have MyRepo. You can add a function, says insert!, into the factory:
defmodule MyFactory do
def insert!(factory, fields \ %{}) do
:user
|> make(fields)
|> MyRepo.insert!()
end
def insert_many!(factory, amount, fields \ %{}) when amount >= 1 do
[%schema{} | _] = entities = make_many(:user, amount, fields)
{_, persisted_entities} = MyRepo.insert_all(schema, entities, returning: true)
persisted_entities
end
end
user = insert!(:user)
users = insert_many!(:user, 10, %{password: "1234567890"})
Link to this section Summary
Functions
Create struct of module from fields.
Returns monotonically increasing unique integer. It would be useful when it comes to generate unique serial IDs.
Lazily evaluate and put lazy_value into name if name does not exist in fields.
Link to this section Types
Link to this section Functions
create_struct(fields, module)
View Sourcecreate_struct(fields :: Enumerable.t(), module :: atom()) :: struct()
Create struct of module from fields.
iex> import Forgery
iex>
iex> create_struct(%{id: 1, username: "john", password: "123456"}, MyUser)
%MyUser{id: 1, password: "123456", username: "john"}
Returns monotonically increasing unique integer. It would be useful when it comes to generate unique serial IDs.
put_new_field(fields, name, lazy_value)
View Source (macro)put_new_field(fields :: Enumerable.t(), name :: any(), lazy_value :: any()) :: map()
Lazily evaluate and put lazy_value into name if name does not exist in fields.
iex> import Forgery
iex>
iex> fields = %{foo: 1}
iex> put_new_field(fields, :foo, 100 + 2)
%{foo: 1}
iex> put_new_field(fields, :bar, 100)
%{foo: 1, bar: 100}
Note that lazy_value is only evaluated when it is needed. For instance, in the
following example, make_foo.() will not be invoked.
iex> import Forgery
iex>
iex> make_foo = fn -> raise("I am invoked") end
iex> fields = %{foo: 1}
iex> put_new_field(fields, :foo, make_foo.())
%{foo: 1}
Link to this section Callbacks
make(factory, fields)
View Sourcemake(factory :: factory(), fields :: Enumerable.t()) :: any()
Makes data from the given factory.
The implementation of this callback should take in the factory name, as well and fields.
make_many(factory, amount, fields)
View Sourcemake_many(factory :: factory(), amount :: integer(), fields :: Enumerable.t()) :: [any()]
Make multiple data from the given factory.
This function is roughly equivalent to:
Enum.map(1..amount, fn _ -> make(factory) end)
Example
make_many(:users, 3)
[
%MyUser{id: 3, password: nil, username: "user3"},
%MyUser{id: 5, password: nil, username: "user4"},
%MyUser{id: 7, password: nil, username: "user5"},
]