ExMachina Hits 1.0 - More Flexible, More Useful and Support for Ecto 2.0

Paul Smith

ExMachina is a library that makes creating test data in Elixir both easy and powerful. Since ExMachina’s first announcement in November 2015 we, and a large number of contributors, have been hard at work making ExMachina more flexible, more useful and more stable than ever. Today we’re announcing the public release of ExMachina 1.0.

ExMachina’s CHANGELOG has a quick rundown of what’s changed.

New factory definition syntax

The most noticeable change is the factory definition syntax. Before 1.0 factories looked like this:

def factory(:user) do
  # ...
end

In 1.0 they look like this:

def user_factory do
  # ...
end

Why? We changed the factory definition syntax for a variety of reasons. It is easier to jump to different factories in your factory module with “jump to symbol” that is available in some editors. But more importantly, the new syntax makes it so that you can put functions related to a factory near the factory they belong to.

Here’s an example from pre-1.0:

def factory(:user) do
  # ... return user struct
end

def factory(:comment) do
  # ... return comment struct
end

def make_admin(user) do
  %{user | admin: true}
end

The make_admin/1 function cannot go underneath the user factory function because Elixir will print a warning that the factory/1 functions are not grouped together.

In ExMachina 1.0 we can group similar functions together more easily:

def user_factory do
  # ... return user struct
end

# Now make_admin/1 is close to the factory it uses
def make_admin(user) do
  %{user | admin: true}
end

def comment_factory do
  # ... return comment struct
end

Uses Ecto terminology: create -> insert

Before 1.0 the functions for working with factories were build and create. This was mostly due to habit after working with ActiveRecord and FactoryBot. Since Ecto uses insert instead of create when talking about saving to the database, we decided to use insert in ExMachina as well.

It’s also worth noting that Ecto is not required when using ExMachina, but if you use it, Ecto version 2.0 or higher is required now.

Introducing ExMachina.Strategy

Previously ExMachina had a build function that returned the struct or map for that factory, and it also had a create function that performed an action with the struct or map returned from build. When using ExMachina with Ecto, create inserted the struct into the database.

Now instead of including build and create, ExMachina only includes build by default. To perform an action with the map or struct returned from a factory (like inserting it in the database, or encoding it as JSON) you would implement an ExMachina.Strategy. This makes ExMachina very flexible because you can have multiple strategies and can easily extract strategies to share with others as hex packages. For example you could have a strategy for encoding as JSON, and another strategy for encoding as XML.

Don’t worry, ExMachina comes with an ExMachina.EctoStrategy for inserting factories to the database. This module is used automatically when you use ExMachina.Ecto in your factory module.

Getting started with ExMachina 1.0

Check out the README for more info about ExMachina.

Upgrading to ExMachina 1.0

We strived to make upgrading to 1.0 as simple as possible. In mix.exs change your ExMachina version to {:ex_machina, "~> 1.0"}, then run your test suite with mix test. ExMachina will raise errors that tell you how to upgrade to 1.0. Most of the time you can run a couple find-and-replaces and you’re ready to go!

See the CHANGELOG for more details about what’s changed and been added in 1.0.