Call Ecto Mix Tasks from Elixir

I’ve got some database operations that run during integration testing which are too complex to be contained in a sandbox connection. I’d like to setup and reset my test database before and after these integration tests. Mix can do this easily from the command line using aliases, but I’m struggling to see how I can insert this functionality into my test setup. I’ve poured through the Mix documentation, but I am still having trouble grasping how to do something like this, and examples don’t seem to be covered very well online.

I imagined adding something like this in ExUnit

setup do
   # some stuff
  on_exit fn ->
   # reset database ["ecto.drop", "ecto.create", "ecto.migrate", "run seeds.exs"]
  end
end

Thanks! :039:

You can run a task with Mix.Task.run/2 (http://elixir-lang.org/docs/stable/mix/Mix.Task.html#run/2)

For example,

Mix.Task.run("ecto.migrate", [])

Keep in mind that this sort of thing won’t work in releases built with exrm or distillery, as mix is not included.

1 Like

Also, if you’re just wanting to reset your database, this is better done by using the ecto sandbox feature:

https://hexdocs.pm/ecto/Ecto.Adapters.SQL.Sandbox.html#content

All your tests will be run inside a transaction, and that transaction will be rolled back when your tests complete.

I’ve tried this approach and I use it for my unit testing. My integration test involves receiving web requests, calling an external API, returning data and writing it to a database. I couldn’t find a way to wrap the whole thing inside the sandbox connection. Even using the {shared, self()} mode.

Thanks for the syntax example! Let me give this a try.

Pardon the necro but I’m getting this error and I cannot figure it out.

defmodule Gaming.Release do
  def hello do
    Mix.Task.run("ecto.create", [])
  end

From my Dockerfile:

CMD ["sh", "-c", "bin/gaming eval Gaming.Release.hello && bin/gaming start"]

** (UndefinedFunctionError) function Mix.Task.run/2 is undefined (module Mix.Task is not available)
Mix.Task.run(“ecto.drop --force”, [])

The whole mix application (and therefore mix tasks) are not included in releases. This is kinda like you don‘t ship e.g. npm with you javascript bundle.

Generally in production I‘d suggest creating databases out of band, given the database user an app uses usually is limited to not even be allowed to create databases.