Phoenix/Elixir testing: beyond mix test
Using commands, tags, arguments, and test watching to improve your testing experience.
Mix is a build tool that provides tasks for creating, compiling, and testing Elixir projects, managing its dependencies, and more.
- mix docs
By leveraging Mix properly, you can gain fine-tuned control of your tests and further improve the convenience and speed of your testing.
You will learn how to:
- run tests by folder
- run test by file
- run a single test in a file
- run tests using tags for specific modules, describe blocks, and tests
- run tests in watch mode
- configure mix commands
- use convenient code editor extensions
You should be able to run your tests with
mix.test in your command line and see something like:
I’m using a demo blog project as an example.
Run tests by folder
You can run
mix test path/to/folder to run all the tests in a specific folder. Here’s an example of running all of your controller tests.
I found that on Windows, this can be a problem because windows autocomplete files using a different syntax.
I’ll edit this post if I find a good solution for this. Oddly it’s only folders that have this issue.
Run tests by file
You can run
mix test path/to/file.ex to run all the tests in a specific folder. Here’s a single controller test called
author_auth_test.ex . You’ll notice that, unlike with folders, running tests by file works correctly with the Windows path syntax.
Run a specific test or describe block
You can run
mix test path/to/file.ex:linenumber to run either a specific test or describe block where
linenumber is the first line of the describe block or test.
Here’s an example test in a describe block. It doesn’t matter what the test does. Just notice that the describe block starts on line 119, and the first test starts on line 120.
Run the describe block on line 119
Or run a single test on line 120
Run tests using tags
You can create tags for modules using @moduletag, describe blocks using @describetag, and specific tests using @tag.
You can then use tags to choose which tests to run using the
--include, --exclude, and --only arguments for mix test.
Using a real code example, I’ll put an @moduletag in my example repository.
then you can use the
--only argument to run this file with
Here’s an example using @describetag and also @tag.
You can selectively run tests using
--exclude . Here’s an example including the describe_example tag but excluding the test_example tag so that only the second test runs.
It’s important to note that includes overwrites excludes (unfortunately, I will update this article if I find a solution) So including a module then excluding a describe block inside of that module, or including a describe block then excluding a test inside of the describe block does not work.
Notice in the next terminal example, 2 tests are run instead of just 1 like you might expect.
In the above, you might notice
--exclude test this is provided by mix to exclude all non-included tests.
Using tags with values
You can also declare tags with a value. For example:
You can then run the tag with
Tags with a different value or the default value will be exempt.
Now that you’ve learned about tags, you may want to consider some recommended tags to use.
It’s useful to be able to skip test(s). Using what you’ve already learned, you could add the
:skip tag then run your tests with
-exclude skip . Instead, however, you can configure your
test_helper.ex file to do this automatically.
ExUnit.configure(exclude: :skip) to your test_helper file. It should look something like this.
Now try adding
@tag :skip to a test. you could also use
Now when you run
mix test that test, describe block, or module will be excluded automatically.
:current to run only the test(s) you are working on.
You already know you can run tests using
--only. To make running
:current more convenient, you can add an alias (see below).
If you find yourself using the same commands repeatedly, you might want to consider making an alias. For example, go to your mix.exs folder, and you should see something like this.
Here’s an example alias using the
:current tag from before.
The name of the alias
test.current is up to your preference. Now you can run
mix test.current .
How to run tests only on affected files
mix test --stale to only execute tests on files changed since the late time you ran
mix test --stale.
Watch files for changes and automatically run tests
There’s a great package called mix-test.watch. You should follow the link if you want the most up-to-date instructions. Here’s my mix.exs file for an example installation.
Once properly installed, you can run
mix test.watch to run tests whenever a file is changed so you can catch broken code as you’re developing.
On Mac or Linux, you should also be able to mix test.watch with arguments
(--stale, --include, --only). However, there seems to be an open issue for Windows users at the time of writing where these arguments are ignored.
Using an extension on your code editor to make running tests easier.
For Visual Studio Code users like myself, a great package called Elixir Test provides useful commands such as running tests in a file, jumping between the test and the affected file, and running the test at your cursor position.
If you use a different editor like Atom or Sublime, I recommend finding a similar plugin. I don’t want to recommend anything that I haven’t used, so if you find one you enjoy, please let me know!
You have learned how to leverage mix to run customizable test suites so that you can run exactly the tests you want. You have also learned about commands, tags, arguments, aliases, test watching, and editor extensions to both improve the performance and convenience of testing.
If you have any questions about this article or would like to comment please do! I’m happy to answer.