There is a lot of good documentation on ExUnit, not the least of which is the ExUnit section at elixir-lang.org.
This little cheat sheet isn’t meant to be comprehensive, but instead is a list of the ExUnit techniques I use on almost every project.
If you want to mark certain tests as pending and automatically exclude them from your test runs, use ExUnit.configure
in your test helper:
Then you can use a tag to mark it as pending which will cause it to be skipped
when you run mix test:
From the output above you can see that the pending test was skipped.
If you actually want to run your pending tests later on, you can do this:
mix test --include pending
If you had some WIP tests, for example, you could select only those to run with the only
flag:
mix test --only wip
If you read the output above, you’ll see that only 1 of the three tests ran.
In this case, only tests marked wip
were run.
Similarly, you could exclude your WIP tests this way:
mix test --exclude wip
I don’t like it when my test output is littered with print or log messages.
If you have Elixir version 1.1+ then you can use ExUnit.CaptureIO
to keep
things clean (among other uses):
If you wrap the noise producing parts in a function and pass it
to capture_io,
then the output will be suppressed.
In the above example “RAWR” will not end up with the test results.
Don’t fret If your version of Elixir doesn’t have CaptureIO. Other techniques may still work.
This isn’t ExUnit specific, per se, but if your test suite depends on a particular service running (e.g Redis), then you can test for it when your test helper gets loaded.
That way, if the service isn’t available then you have the opportunity to abort the test run and print a friendly error message:
This example comes from Andrea Leopardi’s great Redix project.
He uses :get_tcp
to check that he can connect to port 6379. If the connection is successful, he closes the socket and the test run continues. If the connection is not successful, he uses Mix.raise
with a helpful error message to shut things down.
Pretty cool.
It’s not a problem to create support modules directly in your test files, but if they get too big then you may want to move them to their own directory.
This technique comes from Mike Pack’s Poolboy Queue library:
He uses File.ls
to fetch the names of all of the files living under test/support
and then applies Code.require_file
to each one.
Once again, this isn’t ExUnit specific, but this simple technique pops up fairly frequently in my own projects.
The best source on ExUnit assertions is still the docs at elixir-lang.org.
However, I use the following 3 assertions roughly 80% of the time:
They are mercifully self-explanatory:
The final example might warrant an explanation: I’m asserting that my test process will eventually receive the term {:result, "some-result"}
within 100 milliseconds. If the expected message doesn’t arrive on time, the assertion will fail.
assert_receive
and its cousin assert_received are pretty crucial
given that message passing is at the heart of Elixir and Erlang.
I really can’t do any better than the great explanation at the elixir-lang.org site, but in case it’s not obvious:
setup
runs before each testsetup_all
is only run onceon_exit
lives in a setup block and takes a function as an argumentYou’ll use on_exit
in the same way you might use teardown in a different language or test framework.
By default, your application will be started while your tests run.
If you don’t want that behavior, then you could stop it in the test helper:
This is sometimes beneficial if you find that your running application is competing with your unit tests.
Thankfully, you shouldn’t have to do this too much if you’re properly using your application config files. But it’s still nice to have the option.
In case you don’t remember, the name of your app is listed in your mixfile:
To get things started again you only need to call start:
If you’re coming from the Ruby world and would like something similar to VCR to fake HTTP responses, then check out ExVCR.
Similarly, you can use Meck if you want a nice mocking library.
I have used both and they work very well, but you’ll need to take care that you’re not straying too far from the Elixir way if you use them.
Intermittent errors are probably unavoidable if you’re writing concurrent programs.
To help fight this, ExUnit tests are run in a random order via a seed integer.
If a particular run results in errors that you don’t normally see, you can run subsequent tests in the exact same order using that seed as a flag:
mix test --seed <the-seed-that-triggered-errors>
The seed will be printed at the bottom of the test output in the form of
Randomized with seed <THE-SEED-VALUE>
If you look at the output above, you’ll see that we’re passing the integer 668506 to mix.
No matter how many times we run mix test --seed 668506
we’ll always get the tests run in the exact same order.
Getting consistent results goes a long way in squashing pesky errors that only occur some of the time.
If you have a reference to a process ID, you can use
If you have a name instead of a pid, you can use whereis
to lookup the pid before passing it to alive?:
It would probably be worth your time to check out all the cool things that Process can do when you get a chance.
I wrote this post for myself so that I can easily lookup the techniques I use frequently but still manage to forget.
I hope you will find at least some use from it.
Here are some other articles you might be interested in: