# FactoryMan
Elixir test data factories with automatic struct building, database insertion, and customizable hooks.
## Installation
Add FactoryMan to your `mix.exs` dependencies:
```elixir
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:
```elixir
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
end
```
Build and insert in tests:
```elixir
# 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:
```elixir
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()}"
end
```
Then extend the base factory in child factory modules:
```elixir
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
end
```
This 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 `*_list` functions
- **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 `:extends` option
- Hooks for custom transformation logic