Implement a `mix test` wrapper

At work, our current way of running our ExUnit tests is to set several environment variables before the mix test. For example:

URL=http://dev-site.com mix test

or

URL=http://staging-site.com mix test

or

URL=http://pr-1234-staging-site.com mix test

There are a lot of environment variables besides these. Today I tried writing a mix task that would simplify and validate all this input. It works great, for example, I can run the above three tests on the command line like this:

mix my_test --dev
mix my_test --staging
mix my_test --pr 1234

That’s implemented in the mix task ultimately as:

Mix.Shell.IO.cmd(“URL=http://staging-site.com mix test”)

But!

These tests take a long time to run and when I try to Ctrl+C out of them as I normally would, I get my shell command like back, but the tests keep running in the background. What could be going on?

edit: Should I instead call Mix.Tasks.Test.run/1 directly, passing in the argv list? I’d love to do that (it actually solved the Ctrl-C problem), but I don’t know how to set the temporary environment variables in that case.

System env variables can be set via System.put_env/2

defmodule Mix.Tasks.MyTest do
  use Mix.Task

  @impl true
  def run(args) do
    {[{env_name, value}], args} = OptionParser.parse!(args, switches: [dev: :boolean, staging: :boolean, pr: :integer])

    url =
      case env_name do
        :pr -> "http://pr-#{value}-staging-site.com"
        :dev -> "http://dev-site.com"
        :staging -> "http://staging-site.com"
      end

    System.put_env("URL", url)

    Mix.Task.run("test", args)
  end
end
1 Like

That’s perfect! I has wrongly assumed that using System.put_env/2 would export the env var. But it doesn’t. It lives just for the duration of the test and that’s just what I wanted. Thank you very much

1 Like