ExFuzz

Hex Version Hex Docs License

Coverage-guided fuzz testing for Elixir.

The quickest and easiest way to start fuzzing your Elixir projects!

defmodule JasonTest do
  use ExUnit.Case
  use ExFuzz

  @tag timeout: 100
  fuzz "Jason never crashes", data <- binary(), seeds: ["{}", "[1]"] do
    with {:ok, term} <- Jason.decode(data) do
      assert Jason.decode!(Jason.encode!(term)) == term
    end
  end
end

ExFuzz is well-integrated with ExUnit so your fuzz tests can run alongside your regular tests and use the seed corpus as an ever-growing regression suite.

What is fuzz testing?

Fuzz testing runs your code with a stream of generated inputs, looking for ones that crash it or fail an assertion. Coverage-guided fuzzing watches which code each input reaches and builds on the inputs that reach new code, so it finds edge cases that hand-written tests miss.

If you're interested in learning more, see The Fuzzing Book.

Requirements

ExFuzz requires:

Installation

Add ex_fuzz to your dependencies in mix.exs:

def deps do
  [
    {:ex_fuzz, ">= 0.0.0", only: [:dev, :test]}
  ]
end

Then run mix deps.get to install it from Hex.

Note

On unsupported platforms, build ExFuzz from source: install Rust, add {:rustler, "~> 0.38.0", runtime: false} to your dependencies, and set EX_FUZZ_BUILD=1.

Quick start

Fuzz tests run with the rest of your suite under mix test. To run only them:

mix test --only fuzz

To start fuzzing a target, point mix fuzz at the test by its line or name:

mix fuzz test/jason_test.exs:6
mix fuzz test/jason_test.exs:"fuzz Jason never crashes"

Failing inputs are saved as seed corpus to test/fixtures/fuzz/ and replayed by mix test from then on.

See the full documentation for options, configuration and more.

Resources