# `FactoryMan`
[🔗](https://github.com/arcanemachine/factory_man/blob/v0.19.0/lib/factory_man.ex#L1)

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

## Quick Start

```elixir
defmodule MyApp.Factory do
  use FactoryMan, repo: MyApp.Repo

  alias MyApp.Users.User

  deffactory user(params \\ %{}), struct: User do
    base_params = %{username: FactoryMan.sequence("user")}

    Map.merge(base_params, params)
  end
end
```

## Generated Functions

For a factory named `:user` with `struct: User` and a params argument that defaults to an empty
map:

| Function                              | Returns          | Purpose                              |
| ------------------------------------- | ---------------- | ------------------------------------ |
| `build_user_struct/0,1,2`             | `%User{}`        | Struct in memory (not persisted)     |
| `build_user_params/0,1,2`             | `%{}`            | Clean params map derived from struct |
| `build_user_string_params/0,1,2`      | `%{"" => ...}`   | Same, with string keys               |
| `insert_user/0,1,2`                   | `%User{}`        | Built and inserted                   |
| `build_user_struct_list/1,2,3`        | `[%User{}, ...]` | List of structs                      |
| `build_user_params_list/1,2,3`        | `[%{}, ...]`     | List of params maps                  |
| `build_user_string_params_list/1,2,3` | `[%{}, ...]`     | List of string-keyed params maps     |
| `insert_user_list/1,2,3`              | `[%User{}, ...]` | List of inserted records             |
| `insert_user_struct/1,2`              | `%User{}`        | Inserts an already-built struct      |

The insert functions use the default insert target, the repo's `insert!/2`, which requires a
configured repo and a table-backed Ecto schema (see Insert Targets). Each list item is built
independently. `insert_user_struct` has no list counterpart.

Every builder takes options after its params (`build_user_struct/2`, `build_user_struct_list/3`,
and so on). The only builder option is `variants:` (see Variant Factories). Insert functions take
one keyword list: FactoryMan uses `:variants`, and every other option is passed to the insert
target unchanged. The `*_struct` insert forms take no `variants:`, since the struct is already
built:

```elixir
insert_user(%{username: "alice"}, variants: [:admin], returning: true, prefix: "tenant_a")
#                                 └─ FactoryMan ───┘  └─ Ecto (Repo.insert!/2) ───────┘
```

Zero-arity builders and inserts require a default argument in the factory head. For struct
factories, count-only list functions pass `%{}` and are omitted when the head pattern-matches its
argument. Non-struct count-only list functions require a default argument and use that default.

What gets generated depends on the factory configuration:

| Factory configuration    | Value builders | Params builders | Struct builders | Inserts                       |
| ------------------------ | -------------- | --------------- | --------------- | ----------------------------- |
| No `struct:` option      | Yes            | No              | No              | No                            |
| Plain struct             | No             | Yes             | Yes             | With an `insert:` capture     |
| Table-backed Ecto schema | No             | Yes             | Yes             | Yes, unless `insert: false`   |
| Embedded schema          | No             | Yes             | Yes             | With an `insert:` capture     |

Value builders are `build_<name>` and `build_<name>_list`. Any struct factory also gets an
`insert_<name>_via_<target>` family for each `insert_via:` target. `body: :struct` changes how
the struct is built, not which functions are generated.

### Disabling function families

`disable:` switches off function families that a test suite does not use. `true` disables a
family, and `false` enables an inherited one again:

```elixir
use FactoryMan, repo: MyApp.Repo, disable: [string_params: true, insert_list: true]

deffactory user(params \\ %{}), struct: User, disable: [string_params: false] do
  Map.merge(%{username: FactoryMan.sequence("user")}, params)
end
```

| Key                   | Removes                                                   |
| --------------------- | --------------------------------------------------------- |
| `:params`             | `build_*_params/0,1,2` and its list                       |
| `:string_params`      | `build_*_string_params/0,1,2` and its list                |
| `:struct_list`        | `build_*_struct_list/1,2,3`                               |
| `:params_list`        | `build_*_params_list/1,2,3`                               |
| `:string_params_list` | `build_*_string_params_list/1,2,3`                        |
| `:insert_list`        | `insert_*_list/1,2,3`, including `insert_via:` target lists |
| `:non_struct_list`    | A non-struct factory's `build_*_list/1,2,3`                |

- `:params` and `:string_params` are independent: `build_*_string_params` does not use
  `build_*_params`, so either can be disabled alone.
- Everything else is always generated. `build_*_struct` cannot be disabled, since every other
  family builds on it, and inserts are switched off with `insert:` and `insert_via:`.
- `disable:` cascades per key, and variants follow their base factory. `false` on a family that
  is not disabled has no effect.
- A key for the other kind of factory (`:non_struct_list` on a struct factory, or any other key
  on a non-struct factory) raises when written on the factory itself, whatever its value, and is
  ignored when inherited.
- A disabled function's name is free: the module can define a function with that name.

## Defining Factories

`deffactory` defines a named factory with one argument and a body. With `struct:` and the default
`body: :params`, the body returns a map of that struct's fields (a key that is not a field
raises, naming it). With `body: :struct`, it returns the struct itself. Without `struct:`, the
body can return any value, and the factory generates only `build_<name>` and
`build_<name>_list`:

```elixir
deffactory search_opts(overrides \\ []) do
  Keyword.merge([page: 1, per_page: 20], overrides)
end
```

The argument can have any name, and can pattern-match (`%{username: _} = params`). Merge the
params yourself, last, so the caller's values win: FactoryMan does not merge them for you.

## Associations

Declare association builders with `assocs:` (Ecto schema `struct:` only). Each declared key is
resolved before the body, so the body always receives it resolved, and the final
`Map.merge(base_params, params)` stays correct:

```elixir
deffactory author(params \\ %{}), struct: Author, assocs: [user: &build_user_struct/1] do
  base_params = %{name: "Author of #{params.user.username}"}

  Map.merge(base_params, params)
end
```

A builder is a 1-arity function (a local or remote capture, or an anonymous function), a
2-arity function `(params, factory_params)`, or `{builder, options}`. The builder is the
default: an absent key is built with `%{}` (a list key with `[]`), so a `base_params` default for
a declared key is never used.

| Caller supplies      | Singular association                        | Plural association                      |
| -------------------- | ------------------------------------------- | --------------------------------------- |
| Key absent           | Treated as `default:` (`%{}` unless set)    | Treated as `default:` (`[]` unless set) |
| `nil`                | `nil`                                       | Raise; use `[]`                         |
| Params map           | Built by the builder                        | Raise                                   |
| Struct               | Reused unchanged; the builder is not called | Raise                                   |
| List of maps/structs | Raise                                       | Each item resolved in order             |

- Keys must be direct associations; embeds and `:through` associations are not supported.
  Supplied structs and builder results must be the related schema (a singular builder may
  return `nil`, unless the key is `required: true`).
- `default: value` is what an absent key is treated as: `nil` or a params map for a singular
  association, a list of params maps for a plural one. It is evaluated on every build, even when
  the caller supplies the key, so keep it a literal. A record at an association position inside
  `default:` raises.
- `required: true` (singular keys only, not with `default: nil`) raises when the key resolves to
  `nil`, from the caller, a `before_build_params` hook, or the builder. It does not check the
  finished struct.
- Keys resolve top to bottom. A 2-arity builder's `factory_params` holds the caller's params with
  the keys declared above it resolved; the current key and the keys below it are hidden, and
  undeclared keys are visible as given. See
  [Chain associations](cookbook.html#chain-associations).
- A self-referential or mutually recursive default build raises instead of recursing forever.
  This includes recursion that would stop on its own while the key stays absent. Declare such a
  key with `default: nil` (or `default: []`), or pass a value at each level. See
  [Avoid recursive defaults](cookbook.html#avoid-recursive-defaults).
- `assocs:` is evaluated at build time, like the body, and the factory's `params` variable is not
  in scope there. The declaration is validated when the factory first builds.
- `assoc/3,4` and `assoc_list/3,4` apply the same rules to one key, for helper functions and
  values computed in the body (without `required:` or the schema check). They return the
  resolved value without changing the params, so put it back (or drop the key) before the final
  merge.

## Params Functions

For struct factories, `build_*_params` and `build_*_string_params` build the struct and convert
it to a clean map for changesets or controller tests. For Ecto schemas, Ecto metadata,
autogenerated IDs, and unloaded associations are removed; plain structs are converted with
`Map.from_struct/1`:

```elixir
build_user_params(%{username: "alice"})         # %{username: "alice", first_name: nil, ...}
build_user_string_params(%{username: "alice"})  # %{"username" => "alice", ...}
```

Fields whose value is `nil` are kept, so a changeset test sees a `nil` field as given, not as
absent; `nil` embeds are omitted. `belongs_to` associations are removed, and their foreign key is
set when the associated record is persisted. Struct values such as `DateTime` are left untouched.

## Factory Options

Options cascade: parent module -> child module -> individual factory.

**Module-level** (set with `use FactoryMan`): `:repo`, `:extends` (the parent factory module),
`:hooks`, `:insert`, `:insert_via`, `:disable`, `:body`, `:strict`, and `:struct`.

**Factory-level** (set with `deffactory`):

- `:struct` - The struct or Ecto schema to build (enables struct, params, and insert functions)
- `:body` - What the body returns: `:params` (default) or `:struct`. Ignored for non-struct
  factories.
- `:assocs` - Association builders (see Associations). Factory-level only.
- `:strict` - `true`, `false`, or `[allow: [...]]` (see Strict Params). Ignored for non-struct
  factories.
- `:hooks` - Chained with the module's hooks (see Hooks)
- `:repo` - Overrides the module's repo
- `:insert` and `:insert_via` - The default and named insert targets (see Insert Targets)
- `:disable` - Function families to switch off (see Disabling function families)

**Variant-level** (set with `defvariant`): `:for`, `:as`, `:extends`, `:assocs`, and, for a
variant without a body, `:defaults` and `:force` (see Variant Factories). Unknown options raise
at every level.

## Insert Targets

An insert target is the function that inserts a built struct. The default target, set with
`insert:`, is used by `insert_*`, `insert_*_list`, and `insert_*_struct`:

- `:ecto` (the default) - the repo's `insert!/2`. Generated for a table-backed Ecto schema when
  a repo is configured; otherwise nothing is generated. Written on a factory that cannot be
  inserted with Ecto, it raises.
- `false` - no default insert functions.
- A remote capture of arity 2, such as `&MyApp.Factory.put!/2` - generated for any struct
  factory: plain structs, embedded schemas, and Ecto schemas. Anonymous functions and local
  captures raise.

`insert_via:` adds named targets, each with its own family of functions:

```elixir
use FactoryMan, repo: MyApp.Repo, insert_via: [search: &MyApp.Factory.index!/2]

deffactory user(params \\ %{}), struct: User do
  Map.merge(%{username: FactoryMan.sequence("user")}, params)
end

insert_user()                        # MyApp.Repo.insert!/2, with the insert hooks
insert_user_via_search()             # MyApp.Factory.index!/2
insert_user_via_search_list(3)
insert_user_struct_via_search(user)
```

An insert function receives the built struct and the caller's options (without `:variants`),
and returns the inserted struct. A store that takes no options ignores them:
`def index!(struct, _opts)`.

- `insert:` and `insert_via:` cascade like other options. `insert_via:` merges by name: a lower
  level adds a target, replaces the inherited target of the same name, or removes it with
  `name: false` (removing a target that is not inherited raises). The name `ecto` is reserved.
- `insert: false` removes the default family only; `insert_via:` targets remain.
  `disable: [insert_list: true]` removes the list functions of both.
- The insert hooks (`before_insert`, `after_insert`) run for the default target, not for
  `insert_via:` targets. A target that needs more steps does them in its own function.
- Captures and targets do not run the `:ecto` insert's already-inserted check (see Hook
  Pipeline).
- A target receives the struct with any built associations still in place. The `:ecto` insert
  cascades them; a capture or target stores them only if its function does. An
  `after_build_struct` hook applies to every family.
- Variants get their base factory's targets, building through the variant.
- Both options apply to struct factories only: written on a non-struct factory they raise, and
  inherited ones are ignored.

The [Cookbook](cookbook.html#insert-into-other-stores) has recipes for inserting into other
stores.

## Strict Params

`strict: true` catches params that a factory silently ignores. It runs two checks:

1. **Unknown keys**, when building starts (before hooks and the body): every key must be a key
   of the `:struct` option's struct, which includes virtual fields and association keys.
2. **Ignored or changed params**, after the body and its lazy values (before
   `after_build_params`): every field in the params that entered the body (after
   `before_build_params` and `assocs:`) must come out of the body with the same value, compared
   with `==`. A plain map has been kept when each of its keys has been kept, including when the
   body builds a struct such as an embed from it. Function values and association keys are not
   checked.

```elixir
deffactory user(params \\ %{}), struct: User, strict: true do
  %{username: "default"}
end

build_user_struct(%{username: "alice"})
# ** (ArgumentError) strict factory :user in MyApp.Factory ignored or changed params it was given:
#
#      :username - given "alice", built "default"
#    ...
```

Both checks cover every derived function. The second check runs in the base factory's body, so
it sees what the variants pass on; a variant body that drops a caller's key is not checked.

`strict: [allow: [...]]` exempts keys from both checks: a key that is not a field may be passed
(e.g. an input used only to derive other fields), and a field may be changed by the body. An
allowed key that is not a field must not reach the struct, so the body removes it (here with
`Map.pop/3`):

```elixir
deffactory invoice(params \\ %{}), struct: Invoice, strict: [allow: [:line_item_count]] do
  {count, params} = Map.pop(params, :line_item_count, 1)

  Map.merge(%{total: count * 100}, params)
end
```

Set it once in a base factory (`use FactoryMan, strict: true`); a factory can override it. It is
ignored for non-struct factories.

## Hooks

Hooks transform data at specific stages. Every stage has a `before` and an `after` hook.

### Hook Pipeline

```text
build_user_struct:
  params validation → before_build_params → assocs: resolution
  → [factory body + lazy eval] → strict params check → after_build_params
  → before_build_struct → struct!() → after_build_struct

build_user_params (calls build_user_struct internally):
  → strip Ecto metadata (or Map.from_struct/1 for plain structs)

insert_user (calls build_user_struct internally):
  → before_insert → Repo.insert!() → after_insert
```

- The insert hooks belong to the default insert target's functions (`insert_*`,
  `insert_*_list`, and `insert_*_struct`). `insert_via:` targets run no hooks.
- With `body: :struct`, the params-stage hooks (`before_build_params`, `after_build_params`, and
  `before_build_struct`) are skipped; `assocs:` are resolved after params validation, and the
  returned struct is lazily evaluated.
- For non-struct factories, `build_*` runs `before_build_params`, the body with lazy evaluation,
  then `after_build_params`.
- `insert_user_struct/1,2` runs the insert pipeline on an already-built struct (it does not
  resolve associations). Use it after modifying a built struct, so records are shaped the same
  way however they were built; a raw `Repo.insert!/2` skips the insert hooks. With the `:ecto`
  insert, it raises on a struct that has already been inserted (or deleted). To insert a copy on
  purpose, mark it as built first: `Ecto.put_meta(struct, state: :built)`.

### Hook Reference

| Hook                   | Receives     | Returns      | When to Use                                                     |
| ---------------------- | ------------ | ------------ | --------------------------------------------------------------- |
| `:before_build_params` | params (map) | params (map) | Transform or inject params before the factory body runs         |
| `:after_build_params`  | params (map) | params (map) | Modify params after the factory body (e.g. add computed fields) |
| `:before_build_struct` | params (map) | params (map) | Last chance to modify params before `struct!()` is called       |
| `:after_build_struct`  | struct       | struct       | Transform the struct after creation (e.g. set virtual fields)   |
| `:before_insert`       | struct       | struct       | Modify the struct just before it is inserted                    |
| `:after_insert`        | struct       | struct       | Post-process after insertion (e.g. reset associations)          |

A hook is a 1-arity remote capture such as `&__MODULE__.my_hook/1`, or a list of them, run in
order (`after_insert: [&M.reset/1, &M.log/1]`). Hooks are compiled into the generated functions,
so anything else, such as an anonymous function, raises at compile time. See the
[Cookbook](cookbook.html#use-hooks-for-cross-cutting-behavior) for recipes.

### Hook Order

Hooks can be set at three levels, and a hook set at a lower level is chained with the hooks it
inherits instead of replacing them:

1. **Parent module** - `use FactoryMan, hooks: [...]`
2. **Child module** - `use FactoryMan, extends: Parent, hooks: [...]` (any number of levels)
3. **Individual factory** - `deffactory name(params), hooks: [...]`

The order is onion-style, like middleware: the parent wraps the child. For a `before_*` hook
the parent's runs first, and for an `after_*` hook the parent's runs last.

To place a hook (or a list of hooks) explicitly, pass `{hook, placement}`:

| Placement         | Runs                                  | Default for       |
| ----------------- | ------------------------------------- | ----------------- |
| `:after_parent`   | After the inherited hooks             | `before_*` hooks  |
| `:before_parent`  | Before the inherited hooks            | `after_*` hooks   |
| `:replace_parent` | Instead of all of the inherited hooks | -                 |

"Parent" means everything inherited for that hook name, from every level above. Each level is
resolved against the list built so far. For example, with `after_insert`:

```elixir
# Parent module:       after_insert: &P.hook/1                      -> [P]
# Child module:        after_insert: {&C.hook/1, :after_parent}     -> [P, C]
# Factory:             after_insert: &F.hook/1                      -> [F, P, C]
```

Each hook receives the previous hook's result. The same hook set at two levels runs twice. On a
module with no parent, a placement behaves like a plain hook. To switch off the inherited hooks
for one factory, use `hooks: [after_insert: {[], :replace_parent}]`; an empty list with any
other placement raises. Unknown hook names and a hook name set twice at one level raise.

## Factory Inheritance

A child module inherits its parent's options (repo, hooks, insert targets, `strict:`, ...) and
can call the parent's helper functions unqualified (here, a `generate_username/0` defined in
`MyApp.Factory`). Chains can be any length:

```elixir
defmodule MyApp.Factory.Accounts do
  use FactoryMan, extends: MyApp.Factory

  deffactory user(params \\ %{}), struct: User do
    Map.merge(%{username: generate_username()}, params)
  end
end
```

## Variant Factories (`defvariant`)

A variant is a preprocessor for a base factory: its body runs first, on the caller's params,
and passes the result to the base factory:

```elixir
defvariant admin(params \\ %{}), for: :user do
  Map.merge(%{role: "admin"}, params)
end

build_admin_user_struct()   # same as build_user_struct(%{role: "admin"})
```

- Its functions are named `{variant}_{base}` (`build_admin_user_struct`, `insert_admin_user`,
  ...), with the base factory's full family. `as: :mod` renames them (`build_mod_struct`); the
  variant is still listed as `:admin` in `variants:` and `extends:`.
- `for:` must name a factory. A variant is defined after its base factory, in the same module,
  and variant names are unique per factory.
- Params last (`Map.merge(%{role: "admin"}, params)`) makes the variant's values defaults, which
  the caller can override. Params first (`Map.merge(params, %{banned: true})`) forces them: they
  win over the caller and over later variants. See
  [Choose defaults or forced values](cookbook.html#choose-defaults-or-forced-values).

### Variants without a body

A variant that only sets values can declare them instead of writing a body:

```elixir
defvariant admin, for: :user, defaults: %{role: "admin"}
defvariant banned, for: :user, force: %{banned: true}
defvariant banned_admin, for: :user, extends: [:admin, :banned]
```

- `defaults:` is merged under the params (`Map.merge(defaults, params)`), so the caller wins.
  `force:` is merged over them (`Map.merge(params, force)`), so the variant wins. With both, a key
  in both is taken from `force:`.
- A variant without a body needs `defaults:`, `force:`, `extends:`, or `assocs:`, and its head
  takes no argument (`admin` or `admin()`). `defaults:` and `force:` with a do block raise.
- `defaults:` and `force:` are code, evaluated on every build like a body, so they can call
  functions (`defaults: admin_defaults()`); each must evaluate to a map. Lazy values in them
  reach the base factory as params and are resolved there.
- With `assocs:`, the values are merged first and the associations resolved after, so a
  `defaults:` value for a declared key is what the variant's builder builds from.
- Any base factory works, as long as its params are maps.
- A variant without a body never drops a caller's key, so the base factory's strict check sees
  every key the caller passed.
- To keep `mix format` from adding parentheses, add `:factory_man` to `import_deps` in
  `.formatter.exs`. `import_deps` needs the dependency in the environment `mix format` runs in
  (`only: [:dev, :test]`); otherwise add `defvariant: 2` to your own `locals_without_parens`.

### Combining variants with `variants:`

Every generated function of a factory takes a `variants:` option, which applies several
variants in one build:

```elixir
build_user_struct(%{}, variants: [:admin, :confirmed])
insert_user(%{}, variants: [:admin], returning: true)
```

List variants by their `defvariant` name (`:admin`, not `:admin_user`). For variants that merge
params last, the caller's params win, then a later variant wins over an earlier one. The chain
runs from the last variant to the base factory, so a later variant's values reach an earlier one
as params. A variant's own functions count the variant as the first in the list:
`build_admin_user_struct(params, variants: [:confirmed])` is
`build_user_struct(params, variants: [:admin, :confirmed])`. An unknown variant name raises and
lists the known variants.

### Building on other variants with `extends:`

A variant builds on other variants of the same factory with `extends:`, and wins over them:

```elixir
defvariant senior(params \\ %{}), for: :user, extends: [:admin] do
  Map.merge(%{title: "Senior admin"}, params)
end
```

A listed variant brings the variants it extends, and each variant is applied once, at its first
position in the list, so a variant wins over the variants it extends whatever the list order. A
variant is defined after the variants it extends. A variant with only `extends:` and no body
gives a recurring combination a name (see Variants without a body).

## Sequences

```elixir
FactoryMan.sequence("user")                                          # "user0", "user1", ...
FactoryMan.sequence(:email, fn n -> "user#{n}@example.com" end)     # custom formatter
FactoryMan.sequence(:role, ["admin", "moderator", "user"])           # cycles through list
FactoryMan.sequence(:order, fn n -> "ORD-#{n}" end, start_at: 1000) # custom start value
```

`FactoryMan.Sequence.reset/0` clears every counter, for every test. Tests that run at the same
time share the counters, so in async tests reset only the sequence names that test uses:
`FactoryMan.Sequence.reset(:invoice_number)`.

## Lazy Evaluation

Functions in a body's map or keyword list are evaluated at build time. Other values are passed
through unchanged:

```elixir
%{
  created_at: fn -> DateTime.utc_now() end,               # 0-arity: called with no args
  display_name: fn user -> "#{user.username} (User)" end # 1-arity: receives the parent map
}
```

> #### Lazy evaluation ordering {: .warning}
>
> Lazy values are resolved in two passes: the 0-arity functions first, then the 1-arity ones.
> A 1-arity function therefore sees plain values and resolved 0-arity values, but not another
> 1-arity field, which is still a function reference when it runs.

## Embedded Schemas

A factory for an embedded schema generates the struct and params builders. It has no table, so
it gets insert functions only from an `insert:` capture or `insert_via:` targets:

```elixir
deffactory settings(params \\ %{}), struct: MyApp.Users.Settings do
  Map.merge(%{theme: "dark", notifications: true}, params)
end
```

## Direct Struct Factories (`body: :struct`)

With `body: :struct`, the body returns the struct itself, for factories that need full control
over construction. The full function family is still generated, including `build_*_params`, and
lazy values in the struct are resolved. It can be set at the module level and overridden per
factory:

```elixir
deffactory invoice(params \\ %{}), struct: Invoice, body: :struct do
  %Invoice{total: Map.get(params, :total, 100), customer: build_customer_struct()}
end
```

## Cookbook

The [Cookbook](cookbook.html) is a practical progression from a first factory through realistic
defaults, variants, associations, suite organization, hooks, strict params, insert targets, and
advanced presets.

## Reflection and Debugging

Every factory module gets a `__factory_man__/1,2` reflection function:

```elixir
iex> MyApp.Factory.__factory_man__(:opts)
[disable: [], insert_via: [], insert: :ecto, repo: MyApp.Repo]

iex> MyApp.Factories.Users.__factory_man__(:opts, :user)
[disable: [], insert_via: [], insert: :ecto, repo: MyApp.Repo, struct: User]

iex> MyApp.Factories.Users.__factory_man__(:factories)
[:user, :admin_user]

iex> MyApp.Factories.Users.__factory_man__(:variants, :user)
[:admin]
```

- `:opts` shows the resolved options, including each hook name's list in run order, the
  resolved `insert:` and `insert_via:`, and the disabled families (`disable:`). `assocs:` is
  code evaluated at build time, so it does not appear.
- `:factories` lists every factory and variant in the module (variants under their full name),
  for runtime dispatch without building function names from strings.
- `:variants` lists a factory's variants by the names that `variants:` and `extends:` accept.

# `assoc`

```elixir
@spec assoc(map(), atom(), (map() -&gt; any()), keyword()) :: any()
```

Resolve one association from a params map.

Reads `key` from `params` and resolves it with the same rules as the `assocs:` option (there is
no `required:` option here):

| Caller supplies | Result |
| --- | --- |
| key absent | treated as `default:` (`%{}` unless set), then resolved |
| `nil` | `nil` |
| params map | built with `build_fun` |
| a struct | reused unchanged, `build_fun` not called |

Use it where `assocs:` does not fit: an association resolved from a value computed in the body,
a plain helper function, or inside a builder. `params` is not modified; put the result back, or
drop the key, before a final `Map.merge(base_params, params)`.

Unlike `assocs:`, the result is not checked against a schema. A default build that starts
again inside itself raises, as it does for `assocs:` (see Recursion in the module
documentation).

## Options

- `:default` - what an absent key is treated as: `nil` or a params map (default: `%{}`). It is
  evaluated on every call, even when the key is present, so keep it literal.

## Examples

    FactoryMan.assoc(params, :author, &build_user_struct/1)
    FactoryMan.assoc(params, :editor, &build_user_struct/1, default: nil)
    FactoryMan.assoc(params, :author, &build_user_struct(Map.merge(%{role: "writer"}, &1)))

# `assoc_list`

```elixir
@spec assoc_list(map(), atom(), (map() -&gt; any()), keyword()) :: list()
```

Resolve a list association from a params map.

Reads `key` from `params`. An absent key is treated as `default:` (`[]` unless set). An explicit
`nil` raises (use `[]` for no associated values). Each list item must be a params map (built with
`build_fun`, which must not return `nil`) or a struct (reused unchanged); order is preserved.

Like `assoc/3,4`, results are not checked against a schema, and a default build that starts
again inside itself raises.

## Options

- `:default` - what an absent key is treated as: a list of params maps (default: `[]`). It is
  evaluated on every call, even when the key is present, so keep it literal.

## Examples

    FactoryMan.assoc_list(params, :tags, &build_tag_struct/1)
    FactoryMan.assoc_list(params, :tags, &build_tag_struct/1, default: [%{name: "elixir"}])

# `deffactory`
*macro* 

Defines a factory that generates test data.

The `deffactory` macro creates a set of functions for building test data. It works like
defining a function, where you specify the factory name and a parameter (typically `params`).

## Options

- `:struct` - The struct or Ecto schema module to build. When provided, generates struct,
  params, and insert functions.
- `:insert` - The default insert target: `:ecto` (default, the repo's `insert!/2`), `false`
  (no default insert functions), or a remote capture of arity 2 such as
  `&MyApp.Factory.put!/2`. Overrides the module-level value.
- `:insert_via` - Named insert targets, each generating an `insert_*_via_<name>` family:
  `name: capture` adds or replaces a target, and `name: false` removes an inherited one.
- `:disable` - Function families to switch off, as `family: true` (or `family: false` to
  enable an inherited one again). See Disabling function families in the module documentation.
- `:body` - What the factory body returns: `:params` (default, a params map) or `:struct`
  (a struct built directly by the body). Params functions are generated either way (derived
  from the struct), and lazy values are resolved either way. Ignored for non-struct factories.
- `:hooks` - A keyword list of hook functions to apply at different stages, chained with the
  module's hooks (see Hooks)
- `:repo` - Overrides the module-level repo for this factory
- `:assocs` - A keyword list mapping Ecto association keys to builders, resolved before the
  body. Requires an Ecto schema `struct:`. See Associations in the module documentation.
- `:strict` - `true` raises on param keys that are not fields of the `:struct` option's struct,
  and on params the body ignores or changes. `[allow: [...]]` does the same, except for the
  listed keys (see Strict Params). Ignored for non-struct factories.

## Generated Functions

A struct factory generates the `build_*_struct`, `build_*_params`, `build_*_string_params`, and
insert families, and a factory without `struct:` generates `build_*` and `build_*_list`. See
Generated Functions in the module documentation for the full list and the rules that decide
which are generated.

## Examples

    deffactory user(params \\ %{}), struct: User do
      base_params = %{
        username: FactoryMan.sequence("user"),
        email: FactoryMan.sequence(:email, fn n -> "user#{n}@example.com" end)
      }

      Map.merge(base_params, params)
    end

    iex> MyApp.Factory.build_user_params(%{username: "alice"})
    %{username: "alice", email: "user0@example.com", role: nil, ...}

    iex> MyApp.Factory.insert_user(%{role: "admin"})
    %User{id: 1, username: "user1", email: "user1@example.com", role: "admin"}

# `defvariant`
*macro* 

Defines a variant factory without a body, from its options.

    defvariant admin, for: :user, defaults: %{role: "admin"}
    defvariant banned, for: :user, force: %{banned: true}
    defvariant banned_admin, for: :user, extends: [:admin, :banned]

Takes the options of `defvariant/3`, plus:

- `:defaults` - A map merged under the caller's params, so the caller wins.
- `:force` - A map merged over the caller's params, so the variant wins.

Both are evaluated on every build. At least one of `:defaults`, `:force`, `:extends`, and
`:assocs` is required. See Variants without a body in the module documentation.

# `defvariant`
*macro* 

Defines a variant factory that wraps a base factory.

A variant is a preprocessor: it receives the caller's params, transforms them, and delegates
to the base factory. The variant body runs **before** the base factory, not after.

## Example

    deffactory user(params \\ %{}), struct: User do
      base_params = %{username: FactoryMan.sequence("user"), role: "member"}

      Map.merge(base_params, params)
    end

    defvariant admin(params \\ %{}), for: :user do
      base_params = %{role: "admin"}

      Map.merge(base_params, params)
    end

    # Generated: build_admin_user_struct/0,1,2, insert_admin_user/0,1,2, etc.
    # Calling build_admin_user_struct() is equivalent to:
    #   build_user_struct(%{role: "admin"})

## Options

- `:for` - (atom, required) The name of the base factory to wrap (e.g. `:user`). It must name
a factory; a variant builds on other variants with `:extends`.

- `:extends` - A list of variants of the same factory to build on (e.g. `extends: [:admin]`).
They run before this variant's body, so this variant wins over them. Each must be defined
earlier in the module.

- `:as` - Instead of the default `<variant>_<base>` structure used when generating factory
functions, (e.g. `build_admin_user_struct`), you may specify a custom name to use when
generating the factory functions (e.g. `as: :admin` -> `build_admin_struct`)

- `:assocs` - Association builders resolved before the variant body, with the same shape as
the `deffactory` option. The base factory reuses the resolved structs, so a variant can build
an association differently from its base. Requires a base factory with an Ecto schema `struct:`.
The base still enforces its own `required: true`, so a variant can add `required:` to a key but
cannot relax it: a variant `default: nil` on a key the base requires raises on every default
build.

Variants are listed by their name (e.g. `:admin`) in `extends:` and in the `variants:` option
of the generated functions (see Variant Factories in the module documentation).

For a variant without a body, see `defvariant/2`.

# `sequence`

```elixir
@spec sequence(String.t()) :: String.t()
```

Generates a sequence of strings.

The sequence name is used as the beginning of the string. For example, if you
do `FactoryMan.sequence("joe")`, you will get back `"joe0"`, then `"joe1"`, and so on.

## Example

    deffactory user(params \\ %{}), struct: User do
      Map.merge(%{username: FactoryMan.sequence("joe")}, params)
    end

If you want to customize the returned string you can use `sequence/2`.

# `sequence`

```elixir
@spec sequence(any(), (integer() -&gt; any()) | [...]) :: any()
```

Returns the next value in a named sequence.

A formatter function receives the current counter. A list cycles through its items. Returned
values are not guaranteed to be unique.

## Example with a formatter function

    deffactory user(params \\ %{}), struct: User do
      Map.merge(%{email: FactoryMan.sequence(:email, fn n -> "me-#{n}@foo.com" end)}, params)
    end

## Example with a list

    deffactory user(params \\ %{}), struct: User do
      Map.merge(%{name: FactoryMan.sequence(:name, ["Joe", "Mike", "Sarah"])}, params)
    end

# `sequence`

```elixir
@spec sequence(any(), (integer() -&gt; any()), [{:start_at, non_neg_integer()}]) :: any()
```

Returns the next value in a named sequence using a formatter function.

`:start_at` sets the initial counter when the named sequence does not yet exist. It does not change
an existing counter. List formatters are supported by `sequence/2`, not `sequence/3`.

## Example

    deffactory price(params \\ %{}), struct: Price do
      Map.merge(%{cents: FactoryMan.sequence(:cents, fn n -> n end, start_at: 600)}, params)
    end

---

*Consult [api-reference.md](api-reference.md) for complete listing*
