Is there an environment variable that stores the name of the current mix test?

While doing
mix test moduleA
I’m having a problem and it would be helpful if I could know what test is currently running. I basically want to have the code under test capable of printing "Kilroy was here during test: #{Mix.current_test_name}". Is there a system variable that tracks the test name?

You can get the current module and test name from the context:

def MyApp.SomeTest do
  use ExUnit.Case, async: true

  test "whoami", %{module: mod, test: name} do
    assert mod == MyApp.SomeTest
    assert name == :"test whoami"
  end
end
5 Likes

I want to be able to reference the test name from the code being tested not the test code. So in Myapp.moduleA I want to be able to print the test name that is being executed in Myapp.ModuleATest.

Thanks

There is not. For one thing, ExUnit can run tests concurrently, so it is not necessarily the case that any specific test case is happening. You could maybe set some sort of flag manually in a setup block though.

2 Likes

You could pass the test name(given from context, as @mcrumm mentioned) to function param, and make some default value. In other environments call without the param, as we do with other test-dependent logic. It’s the only way i guess.

Maybe I am missing something very obvious here but why not use mix test --failed? That will only re-run the tests that failed (duh!) and you’ll be able to look at a much smaller console output.

In addition to this – or only do this – you can just tag a test like so: @tag :wip and then run mix test --only wip which will only execute tests with the tag.

The problem doesn’t cause a test failure. I’m actually getting unexpected Mox calls, which aren’t causing test failures and wander with each test run (i.e. because of the random ordering), but don’t seem to have a pattern even if I run trace.

I think there are a number of good tidbits here, so thanks all. @benwilson512’s point that tests could be concurrent (although many of mine are not) is a good justification for not being able to do this. @mcrumm provided the information necessary to create some sort of environment variable that I can set, and then inspect from operational code, so I’ll try that.

In theory, it should be possible to register your test name in a registry, and then check the $callers and $ancestors to find what the name of the test is in the registry based off of those. This wouldn’t help Sinc’s problem because if you’re getting unexpected Mox calls, it would be using the same mechanism to attempt to find the test name.

@Sinc are you using spawnor spawn_link anywhere instead of Task? Are you spinning up GenServers? Those are the two places you should look. The other problem is if you’re spinning up a Task that doesn’t share a lifetime with the test. So you might need to change something from Task.start to Task.start_link, or, if you’re using Task.Supervisor (which you should be), starting a supervisor in a setup block, and passing that supervisor to be used instead of a global supervisor.

While this strategy is very useful in many situations, this would only help with processes that are spawned from a test process. It doesn’t help with code booted in your application tree (like your DB connection pool) that isn’t really part of any specific test, nor was started by any.