Elixir ExUnit Tests - Comprehensive Guide

Learn how to write and run tests in Elixir using ExUnit. This guide covers Mix projects, inline tests, debugging with IEx.pry, and best practices for Elixir testing.

Elixir Testing with ExUnit

Elixir Testing with ExUnit

Testing is a fundamental part of the Elixir platform, powered by ExUnit. This guide will walk you through defining and running tests effectively.

Defining Tests in Mix Projects

If you are working within a Mix Application, the standard practice is to place your test files in the test directory. These tests are automatically discovered and executed when you run the command mix test from your project's root directory. Mix sets up the necessary environment for ExUnit to run your tests seamlessly.

Inline Tests

For simpler scenarios or quick checks, you can also define tests directly at the end of any Elixir file. These tests will be executed automatically during the compilation process of that file. This is a convenient way to ensure that specific code snippets behave as expected without needing a separate test file.

Test Boilerplate

A typical Elixir test file using ExUnit follows a specific structure. Here's a basic example:

# The ExUnit.start call is often handled automatically by Mix projects
# in a file like test_helper.exs. You may need it for standalone files.
# ExUnit.start

defmodule MyModuleTest do
  use ExUnit.Case

  test "should assert the truth" do
    assert 1 + 1 == 2
  end

  test "another example test" do
    refute is_nil(self())
  end
end

Debugging Tests with IEx.pry

Debugging within the context of a running test is made easy with Elixir's interactive shell (IEx). Follow these steps to set up and use debugging:

  1. At the top of your test file, before the defmodule declaration, add the following line to require IEx:

    require IEx
  2. Inside your test function, at the exact point where you wish to pause execution and enter an IEx session, insert the following line:

    IEx.pry()
  3. Run your tests using a specific invocation that prevents timeouts and allows you to interact with the debugger. Replace <test specification> with a pattern to select specific tests if needed (e.g., MyModuleTest or "should assert the truth"):

    iex -S mix test --trace <test specification>

    The --trace flag is crucial as it ensures that IEx does not time out, allowing you to step through your code and inspect variables when you hit IEx.pry().

External Resources