ExUnit Atlas

QualityLicense: MIT

ExUnit Atlas turns ordinary ExUnit tests into a readable map of the behavior your application guarantees.

It is not a new test framework. ExUnit remains responsible for tests, assertions, failures, stacktraces, terminal output, and exit codes. Atlas adds two small annotations—step and check—and generates:

ex_unit_atlas_report/
├── report.json
└── index.html

The HTML report is a self-contained document with no server, JavaScript, external assets, or frontend build step.

Why Atlas?

Test names are useful, but a test often guarantees more than its name can say. Atlas lets the test body expose those guarantees without replacing familiar ExUnit structure:

ExUnitAtlas interpretation
module or filebehavior group
describebehavior section
testscenario
stepmeaningful setup or action
checknamed guarantee
ExUnit resultscenario status

The resulting report is meant to be read from top to bottom as business behavior, while technical metadata remains available when needed.

Installation

Add Atlas as a test-only dependency:

def deps do
[
{:ex_unit_atlas, "~> 0.1.0", only: :test, runtime: false}
]
end

Run mix deps.get.

In test/test_helper.exs, replace the existing ExUnit.start() call with:

ExUnit.start(
formatters: [
ExUnit.CLIFormatter,
ExUnitAtlas.Formatter
]
)

Keep the standard CLI formatter. Atlas complements it; it does not print the normal test results.

Usage

Add use ExUnitAtlas after use ExUnit.Case or your project-specific case template:

defmodule Shop.SaleTest do
use ExUnit.Case, async: true
use ExUnitAtlas
describe "Sales" do
test "cash sales are fiscalized" do
sale =
step "Create a completed cash sale" do
%{payment_type: :cash, status: :completed}
end
check "The completed cash sale is eligible for fiscalization" do
assert sale.payment_type == :cash
assert sale.status == :completed
end
end
end
end

Run tests normally:

mix test

Open ex_unit_atlas_report/index.html in a browser, or consume ex_unit_atlas_report/report.json from another tool.

Choosing useful steps and checks

Use a step for preparation or an action that carries business meaning. Use a check to name a guarantee and keep regular assert and refute expressions inside it.

Do not add a step only because every scenario appears to need one. This is perfectly valid:

test "disabled fiscalization overrides the request" do
check "Fiscalization remains disabled" do
refute should_fiscalize?(request, %{fiscalization_type: :disabled})
end
end

The report becomes valuable when names explain behavior—not when every line of test code receives a label.

Runtime semantics

Current limitations

Documentation

Requirements

Contributing

Bug reports and focused improvements are welcome. Read CONTRIBUTING.md before opening a pull request. By participating, you agree to follow the Code of Conduct.

For release validation and publication, see RELEASING.md.

License

ExUnit Atlas is available under the MIT License.