# FactoryMan
Elixir test data factories with automatic struct building, database insertion, and customizable hooks.
> NOTE: FactoryMan is heavily inspired by [ExMachina](https://hex.pm/packages/ex_machina), and copies some code from it in some cases (e.g. for sequences). However, FactoryMan is not a clone of ExMachina. See the examples in the documentation to see what sets us apart!
## Installation
Add FactoryMan to your `mix.exs` dependencies:
```elixir
def deps do
[
{:factory_man, "0.1.0"}
]
end
```
Then run `mix deps.get`.
No further configuration should be necessary.
## Quick Start
Create a factory module in your project's `test/support/` directory:
`test/support/factory.ex`
```elixir
defmodule MyApp.Factory do
use FactoryMan, repo: MyApp.Repo
alias MyApp.Users.User
deffactory user(params \\ %{}), struct: User do
base_params = %{username: "user-#{System.os_time()}"}
Map.merge(base_params, params)
end
end
```
Build and insert some test data:
```elixir
# Build params (e.g. for testing changesets)
iex> MyApp.Factory.build_user_params(%{username: "test_user"})
%{id: nil, username: "test_user"}
# Build a struct (not persisted)
iex> MyApp.Factory.build_user_struct(%{username: "test_user"})
%User{id: nil, username: "test_user"}
# Insert into the database
iex> MyApp.Factory.insert_user!(%{username: "test_user"})
%User{id: 1, username: "test_user"}
# Insert multiple items in a single statement
iex> MyApp.Factory.insert_user_list!(3)
[%User{id: 1, ...}, %User{id: 2, ...}, %User{id: 3, ...}]
```
## Base Factory Pattern (Optional)
For larger projects, you may want to share common configuration across multiple factory modules. FactoryMan allows you to create a base factory module with shared settings:
```elixir
defmodule MyApp.Factory do
# Define the base factory options here
use FactoryMan, repo: MyApp.Repo
# You may define generic factory helpers in this module as well
def generate_username, do: "user-#{System.os_time()}"
end
```
Then extend the base factory in child factory modules:
```elixir
defmodule MyApp.Factory.ChildFactory do
# Extend the base factory
use FactoryMan, extends: MyApp.Factory
alias MyApp.Factory
alias MyApp.Users.User
# Child factories in this module inherit the options set in the base factory module
deffactory user(params \\ %{}), struct: User do
%{username: Factory.generate_username()} |> Map.merge(params)
end
end
```
Child factories are typically placed in `test/support/factory/[your_context].ex` and extend the base factory to inherit common configuration like repo settings and hooks.
The directory structure is up to you, but it is recommended to make a factory module for each context in your application code. Keeping the filesystem hierarchies the same tends to make it easier to remember which factory is where.
> #### Tip {: .tip}
>
> The base factory pattern is completely optional. Use whatever structure fits your project or personal tastes.
## Features
- Easy factories - Define factories with minimal boilerplate
- Generated functions - Build params (for testing changesets), structs, and lists of items
- Database insertion - Built-in `insert_` functions with configurable repo
- List factories - Create multiple records with `*_list` functions
- Sequence generation - Automatic unique value generation for usernames, emails, etc.
- Lazy evaluation - Compute values at build time
- Factory inheritance - Share config from parent factories to reduce boilerplate
- Hooks - Apply custom transformations to data before/after building or inserting a factory item
## Documentation
Full documentation is available in [the `FactoryMan` module](https://hexdocs.pm/factory_man/FactoryMan.html).