I wrote a
Mix.Task that’s supposed to be run in a specific environment (
:test) and nowhere else.
The task uses dependencies that are present only in the test environment.
I can set
preferred_cli_env to make sure that the task automatically runs in the test environment when I invoke it, so that’s good.
However, when I compile my app in another environment (e.g.
:dev) mix will try to compile that task, resulting in errors or at the very least compiler’s warnings due to the missing dependencies.
Is there an elegant way to solve this problem? I can think of a few options:
- Make the test-only dependencies used by the task available in all environments
- Enclose the code in my task in a huge
if Mix.env() == :test do ... end clause
- Split tasks into directories: (i.e.
task/dev etc.) and play around with the
elixirc_paths option to disable compilation in specific environments
The last option is the only one appealing to me, but I think
elixirc_paths only accepts a list of directories, and since
lib is already in there, the tasks would have be moved out of
lib. I wish there was a way to selectively exclude a directory, or even better a single file, but I believe that’s not possible.
Any ideas? Thank you very much in advance!
You can always wrap the entire module code?
if Mix.env() == :dev do
defmodule XYZ do
Option 4: Make the mix task not fail in other envs by just printing an error message instead of doing what it normally does.
@LostKobrakai thanks! The problem is getting rid of the compile-time warnings caused by the non-existent dependencies.
Yep, that’s probably the best solution so far. I find it ugly, but I guess I’ll go for it thanks
I was wondering if there is a way to configure the directory where tasks should reside. It looks like it has to be “lib/mix/tasks”.
That would be an elegant solution: having different task folders.
That way the test tasks would only be compiled in the test environment
A cleaner solution could be to use the
elixirc_paths option from
And then further below:
defp elixirc_paths(:staging), do: ["lib", "test/support", "test/integration"]
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
That way you can encapsulate functionality in directories and wall it.
I mentioned this in my first message.
The problem is that you can’t easily exclude/include subfolders of lib (where the tasks are located). You either compile everything under lib, or nothing.
And moving tasks to different directories doesn’t appear to be supported
Yeah, if you can encapsulate then you can use this but if you can’t, it’s best if you go for good old
if Mix.env() == ...
yes good old if is always the solution to most of our problems!
This should work. Elixir generally does not care which files define a module.
Yep it does. I had tried it before and it didn’t work as soon as I’d move the tasks outside of the lib folder (for example under
test/tasks), but that was because I had simply forgotten to add the new tasks directory to the
elixirc_paths for the
Cool, so now I can put the test tasks under
test/tasks and everything’s nice and clean again.
Thanks for the hint!