Protocol consolidation vs mix test --no-compile

Problem description

I always assumed that there would be no practical difference between:

  1. compiling first, running tests without compilation second
    MIX_ENV=test mix compile && mix test --no-compile
  2. compiling and running tests all in one go
    mix test

But it seems that in the first case, protocols are not consolidated.

I am working on a project that requires writing a test that checks if a protocol was implemented for a given struct. I’m calling __protocol__(:impl) on the protocol in the test (GitHub gist) to get the list of modules that implement it. This doesn’t work if I run tests with --no-compile, even though the project is already compiled and unchanged. And by “doesn’t work” I mean the call returns :not_consolidated instead of {:consolidated, modules}.


  1. What are the differences between MIX_ENV=test mix compile && mix test --no-compile and mix test (also unrelated to protocols)?

  2. How can I check which modules implement the protocol in a test while still using MIX_ENV=test mix compile && mix test --no-compile?

I recognize that my needs are unusual. This is an educational project where the implementation will be submitted by students and can be anything, hence the need to assert on implementation details. I want to run the tests with --no-compile because I am working with stdout and stderr and I don’t want compilation-related output in there (in theory there shouldn’t be any since the project is freshly compiled so I might be able to get out of this problem by removing the flag, but I would still like to understand what’s going on).

It is a bug. I will fix it on master soon. Thanks!