FactoryMan

Elixir test data factories with automatic struct building, database insertion, and customizable hooks.

NOTE: FactoryMan is heavily inspired by ExMachina, 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:

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

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:

# 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:

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:

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

The base factory pattern is completely optional. Use whatever structure fits your project or personal tastes.

Features

Documentation

Full documentation is available in the FactoryMan module.