FactoryMan

An Elixir library for generating test data. Define factories with deffactory, and FactoryMan generates functions for building params, structs, and database records.

Inspired by ExMachina, but with a different API and feature set.

Installation

Add FactoryMan to your mix.exs dependencies:

def deps do
[
{:factory_man, "~> 0.9.0", only: [:dev, :test]}
]
end

Then run mix deps.get.

Quick Tour

Define factories:

defmodule MyApp.Factory do
use FactoryMan, repo: MyApp.Repo
alias MyApp.Accounts.User
alias MyApp.Blog.Post
# Basic factory
deffactory user(params \\ %{}), struct: User do
base_params = %{
username: sequence("user"),
email: sequence(:email, fn n -> "user#{n}@example.com" end),
role: sequence(:role, ["admin", "mod", "user"]),
joined_at: fn -> DateTime.utc_now() end,
display: fn user -> "#{user.username} (#{user.role})" end
}
Map.merge(base_params, params)
end
# Variant: Preprocesses params, then delegates to the base factory
defvariant admin(params \\ %{}), for: :user do
base_params = %{role: "admin"}
Map.merge(base_params, params)
end
# Associations: Call other factories to build related records
deffactory post(params \\ %{}), struct: Post do
base_params = %{
title: sequence("post", fn n -> "Post ##{n}" end),
author: Map.get_lazy(params, :author, fn -> build_user_struct() end)
}
Map.merge(base_params, params)
end
# Struct-less factories: Only generates `build_*` and `build_*_list` functions
deffactory api_payload(params \\ %{}) do
base_params = %{action: "create", resource: "user"}
Map.merge(base_params, params)
end
end

Each factory generates a family of functions:

iex> Factory.build_user_struct()
%User{username: "user1", email: "user1@example.com", ...}
iex> Factory.build_user_params()
%{username: "user0", email: "user0@example.com", role: "admin", ...}
iex> Factory.insert_user()
%User{id: 1, username: "user2", ...}
iex> Factory.insert_user_list(3)
[%User{id: 2, ...}, %User{id: 3, ...}, %User{id: 4, ...}]
iex> Factory.build_admin_user_struct()
%User{role: "admin", username: "user3", ...}
iex> Factory.build_api_payload()
%{action: "create", resource: "user"}

How It Works

You write one factory, and FactoryMan generates the rest:

Factories without a struct: option are simpler: they generate build_<name> and build_<name>_list, and the body can return any value (maps, keyword lists, strings, ...).

Which Function Should I Use?

A common mistake is inserting records when a plain struct would suffice. If you only need an ID for a foreign key, consider whether the test actually needs that constraint enforced.

Keep the base factory focused on shared config (repo, hooks, helpers). Child factories use extends: to inherit that config, and mirror your application's context structure:

test/support/
factory.ex # Base factory (config, hooks, shared helpers)
factory/
accounts.ex # MyApp.Factory.Accounts (extends MyApp.Factory)
blog.ex # MyApp.Factory.Blog (extends MyApp.Factory)
blog/comments.ex # MyApp.Factory.Blog.Comments (extends MyApp.Factory)

Going Further

The full reference lives in the FactoryMan module documentation, including: