Using mix.exs file to setup test suite, then breaks another apps test suite

Hello, in one of my applications, we drop the databases at the end of the test and then it resets it. This was something we did because we could only run tests a certain number of times (for a reason I don’t quite understand) before we would have to reset the database. To get around this we now do this:

    [
      setup: ["deps.get", "ecto.setup"],
      "ecto.setup": ["ecto.create --quiet", "ecto.migrate --quiet"],
      "ecto.reset": ["ecto.drop --force-drop --quiet", "ecto.setup"],
      test: ["ecto.setup", "test", "ecto.drop --force-drop --quiet"]
    ]
  end

However, now when I go into another app and run tests somewhere else I get another error. When I run MIX_ENV=test mix ecto.reset from the command line in the same app where I did all of the aliases, the test database that I was needing is recreated. Could I write a script to run it from the folder where my app lives, like I would if I did it on the command line? Then could I enter that script into the aliases?

I am open to other solutions as well.

This typically happens when your database is inserting data outside of the SQL sandbox. The SQL sandbox help you ensure that all data created in a test happens in a transaction, which is reverted at the end of the test, so the database go back to “clean”. If something inserts data outside of it, then it fails. You can verify this by no longer resetting the database afterwards and see if any of the tables have data in it.

Can you please expand what is the other app? Is this an umbrella application? Or are those different apps? Do they use the same database name by any chance?


In any case, note that a Mix task only runs once. Your mix test is running mix ecto.setup at the beginning and at the end, but I believe the one at the end does not run, because mix ecto.setup already ran at the beginning. You can do MIX_DEBUG=1 mix test to confirm! You can address this by doing:

"ecto.reset": ["ecto.drop --force-drop --quiet", &Mix.Task.rerun("ecto.setup", &1)]
1 Like

Hey Jose, thank you for your help. Yeah we have one app that is not an umbrella app and another app that is an umbrella app that uses the same database. I and another teammate of mine are playing around with the solution you gave us.

  defp aliases do
    [
      setup: ["deps.get", "ecto.setup"],
      "ecto.setup": ["ecto.create --quiet", "ecto.migrate --quiet"],
      "ecto.reset": ["ecto.drop --force-drop --quiet", &Mix.Task.rerun("ecto.setup", &1)],
      test: ["test", "ecto.reset"]
    ]
  end

Now this is giving us an error in the app that I have the aliases set in.


  * The database does not exist
  * The "******" table, which Ecto uses for managing
    migrations, was defined by another library
  * There is a deadlock while migrating (such as using concurrent
    indexes with a migration_lock)

To fix the first issue, run "mix ecto.create".

To address the second, you can run "mix ecto.drop" followed by
"mix ecto.create". Alternatively you may configure Ecto to use
another table and/or repository for managing migrations:

    config :content_schema, ContentSchema.Repo,
      migration_source: "some_other_table_for_schema_migrations",
      migration_repo: AnotherRepoForSchemaMigrations

The full error report is shown below.

12:37:33.670 [error] Postgrex.Protocol (#PID<0.549.0>) disconnected: ** (DBConnection.ConnectionError) tcp send: closed

How are migrations handled in this scenario? Do they live in just one of the applications, or are they copied to both?

1 Like

We ended up needing to just make a small switch in the below:

from:
test: [“ecto.setup”, “test”, “ecto.drop --force-drop --quiet”]

to:
test: [ “test”, “ecto.setup”]