If you frequently work in umbrella apps in Elixir, you know that there are a couple of small pain points in the testing process related to folder structure and file locations. I have been working in umbrella apps for the past year, and I deal with these regularly. In this article I will explain the changes coming in Elixir 1.9 that will finally relieve those pain points.
Recursive Tasks and Umbrellas
mix test
is a recursive task in Elixir. This means that when you run the task in an umbrella app, Elixir iterates through each of the child apps and runs the task on that child app. Recursive tasks are super helpful because your child apps can have different behavior for a given task and the recursion will run each as it was configured. The tasks for each child are run from the base of the child app, not the root of the umbrella app, allowing tasks to behave the same when run recursively from the umbrella level as from the child level.
The Problem
The issues with testing umbrella apps in Elixir prior to 1.9 arises when you want to pass a file path to mix test
to test only that one file. For example, you would specify mix test test/foo/my_test.exs
to test a file in the foo
child app, even though the file relative to the umbrella app is actually apps/foo/test/foo/my_test.exs
. This disconnect means that you cannot use tab-completion to specify the file you want to test, as apps/foo/test/foo/my_test.exs
doesn’t exist relative to the child app’s base. Furthermore you can’t use features like VSCode tasks to quickly test the current file, as VSCode will include apps/foo
in the path it injects into the task execution.
A second frustration with testing single files on umbrella apps is that the command is run on every child app even though only one app is going to have the specified file in it. This results in Paths given to "mix test" did not match any directory/file
warnings in the console for every child app other than the one the file exists in, pushing the information you want to see up and potentially out of sight in the console.
A third issue with regards to testing paths is that the path in the output of a failed test doesn’t include apps/foo
, so it is not clickable in enhanced consoles that support clicking files, such as the VSCode terminal.
The Resolution
One of the great things about working in Elixir is the fact that if you run into an issue with the language, you can either report it and get it resolved fast, or just dive in and fix it yourself and have it merged in no time. One of the many benefits of working at DockYard is the “DockYard Day.” Monday through Thursday are client days; Friday is a DockYard Day, where we can work on a project of our choosing including contributing to Open Source. After working without tab-completion and clickability for too long, I finally decided on a recent DockYard Day to dive in and see what it would take to resolve these issues.
After some investigation, I took a shot at improving mix test
to recognize paths that include apps/app_name
. José suggested some improvements to the approach, which added the side-effect of skipping the test run altogether for child apps that don’t contain that file, resolving the second issue mentioned above.
In the discussion on the PR, I mentioned that resolving the third issue, including the full relative path in test outputs, was on my to-do list. When I came back the next DockYard Day to implement the fix for this, I found that it had already been implemented by José, which was awesome.
The Result
I have been running the master branch of Elixir ever since, and it is refreshing to be able to use tab completion and click file paths in failed tests again for the first time in a year. A week or so after this all wrapped up, the first release candidate for Elixir 1.9 was announced, so it won’t be long before everyone can enjoy these improvements.
DockYard is a digital product agency offering custom software, mobile, and web application development consulting. We provide exceptional professional services in strategy, user experience, design, and full stack engineering using Ember.js and Elixir. With a nationwide staff, we’ve got consultants in key markets across the United States, including San Francisco, San Diego, Phoenix, Detroit, Pittsburgh, Baltimore, Hartford, and New York.