FactoryMan
Elixir test data factories with automatic struct building, database insertion, and customizable hooks.
Installation
Add FactoryMan to your mix.exs dependencies:
def deps do
[
{:factory_man, "0.1.0"}
]
end
Then run mix deps.get.
Quick Start
Create a factory module in your test support directory:
defmodule MyApp.Factories.Users 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
endBuild and insert in tests:
# Build a struct (not persisted)
iex> MyApp.Factories.Users.build_user_struct(%{username: "test_user"})
%User{id: nil, username: "test_user"}
# Insert into database
iex> MyApp.Factories.Users.insert_user!(%{username: "test_user"})
%User{id: 1, username: "test_user"}
# Insert multiple records
iex> MyApp.Factories.Users.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. Create a base factory module with shared settings:
defmodule MyApp.Factory do
# Define base factory options, which can be extended in child factories:
use FactoryMan,
repo: MyApp.Repo
# Helper functions available to all child factories
def generate_username, do: "user-#{System.os_time()}"
endThen extend the base factory in child factory modules:
defmodule MyApp.Factories.Users do
use FactoryMan, extends: MyApp.Factory
alias MyApp.Users.User
deffactory user(params \\ %{}), struct: User do
%{username: generate_username()} |> Map.merge(params)
end
end
defmodule MyApp.Factories.Posts do
use FactoryMan, extends: MyApp.Factory
alias MyApp.Posts.Post
alias MyApp.Factories.Users
deffactory post(params \\ %{}), struct: Post do
base_params = %{
title: "Test Post",
author_id: params[:author_id] || Users.insert_user!().id
}
Map.merge(base_params, params)
end
endThis pattern is optional - use whatever structure fits your project.
Features
- Simple factories - Define factories with minimal boilerplate
- Automatic struct building - Define Ecto schemas and FactoryMan handles the rest
- Database insertion - Built-in
insert_functions with configurable repo - List factories - Create multiple records with
*_listfunctions - Sequence generation - Automatic unique value generation for usernames, emails, etc.
- Lazy evaluation - Compute values at build time with 0 or 1 arity functions
- Factory composition - Nest factories for complex associations
- Optional inheritance - Share config across modules with
:extends - Hooks - Transform data at build, insert, or any stage with custom hooks
Documentation
Full documentation is available in the FactoryMan module:
- Basic factory creation and usage
- List factories for bulk data creation
- Sequence generation for unique values
- Lazy evaluation for computed attributes
-
Factory inheritance with the
:extendsoption - Hooks for custom transformation logic