An Elixir library to generate test data recursively with traits
The package can be installed
by adding refactory to your list of dependencies in mix.exs:
def deps do
[
{:refactory, "~> 0.1.1", only: :test}
]
endDocumentation can found at https://hexdocs.pm/refactory/.
Refactory allows generating Ecto records with nested overrides for your tests.
To start using Refactory, first define a factory module:
defmodule MyApp.Factory do
use Refactory, repo: MyApp.Repo
endThe factory module has two functions:
build/2generates an Ecto record with the given traits appliedcreate/2inserts an Ecto record into the database
A trait can be
- a
Mapin which each key-value pair is either- a field with its value
- an association with a trait (for
belongs_to,has_one, andembeds_one) - soon: an association with a list of traits (for
has_manyandembeds_many)
- a custom trait defined in the factory module (see below)
- a
Tuplewith multiple traits to be applied
defmodule MyApp.Factory do
use Refactory, repo: MyApp.Repo
end
MyApp.Factory.build(MyApp.List, %{
title: "Refined List",
created_by_user: %{email: "[email protected]"}
})
%MyApp.List{
title: "Refined List",
created_by_user: %MyApp.User{
email: "[email protected]"
}
}Default traits can be defined in the factory module. They are always applied first.
defmodule MyApp.Factory do
use Refactory, repo: MyApp.Repo
def trait(MyApp.List, :default) do
%{
title: "Default Title"
}
end
end
MyApp.Factory.build(MyApp.List)
%MyApp.List{title: "Default Title"}Custom traits can be defined in the factory module and then used by their name.
defmodule MyApp.Factory do
use Refactory, repo: MyApp.Repo
def trait(MyApp.List, :default) do
%{
title: "Default Title"
}
end
def trait(MyApp.List, :with_admin_user) do
%{
created_by_user: %{
role: :admin
}
}
end
end
MyApp.Factory.build(MyApp.List, :with_admin_user)
%MyApp.List{title: "Default Title", created_by_user: %MyApp.User{role: :admin}}To my knowledge, this is the only factory library that supports recursive traits, providing a powerful declarative appraoch to (test) data generation.
Recursive and/or nested approaches might be tricky in non-functional programming languages, because the resulting objects often encapsulate internal state. In Elixir, however, data structures are cleanly separated from behavior, making it a great field of application for recursive data structure generation.
This project is sponsored and kindly supported by Team Engine.
If you'd like to join us working on Dx and Refactory as a contractor, please reach out to @arnodirlam.