Phoenix/Elixir testing: beyond mix test

Brooklin Myers
7 min readJun 19, 2021

Using commands, tags, arguments, and test watching to improve your testing experience.

Coming from a Javascript background, testing Phoenix and Elixir is a dream come true. Tests are extremely fast, often taking mere seconds to run. Developers who are familiar with elixir should be aware of the Mix module.

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

Assuming you already have a phoenix project up and running (if you don’t, you can read my article or read the docs)

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. ./path/to/folder

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. ./path/to/file.ex .

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 mix.test

Here’s an example using @describetag and also @tag.

You can selectively run tests using --include and --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 tag:value

Tags with a different value or the default value will be exempt.

Recommended Tags

Now that you’ve learned about tags, you may want to consider some recommended tags to use.

Skip

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.

Add 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 @describetag or @moduletag .

Now when you run mix test that test, describe block, or module will be excluded automatically.

Current

use :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).

Mix aliases

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

Run 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!

Conclusion

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.

--

--

Brooklin Myers

Software Engineer. I create educational content focused on technology for mobile and web applications.