This library, inspired by difftastic-ruby, provides integration with Difftastic - a next-level diffing tool based on tree-sitter.
ExUnit's default diffs are great for Elixir data structures, but when you have a big chunk of data, for example a HTML file (renderd email or LiveView component), it falls a bit short.
With Difftastic we can regain control and have much nicer, easier to reason about, diffs.
It also works nice with Elixir data structures, although the benefit is not as obvious as with HTML.
The package can be installed by adding difftastic
to your list of dependencies in mix.exs
:
def deps do
[
{:difftastic, "~> 0.1.0"}
]
end
This library relies on Difftastic being installed on your machine. It won't download or install it for you (unlike the Ruby counterpart). Refer to your system or distribution package manager to see how to install it. Tested examples:
- In Arch Linux:
pacman -S difftastic
- In MacOS:
brew install difftastic
Having the difft
executable available and in PATH
, you can run difftastic like this:
Difftastic.diff(html_1, html_2, "html")
The library also provides integration with ExUnit via importing Difftastic.Assertions
module.
defmodule UuidGeneratorTest do
use ExUnit.Case
import Difftastic.Assertions
test "diff html" do
re1 = Req.get!("https://www.uuidgenerator.net/").body
re2 = Req.get!("https://www.uuidgenerator.net/").body
difft_assert_equal(re1, re2)
end
end
Warning
Using difft_assert_equal
brings a certain performance penalty. Difftastic is a CLI tool and using it from Elixir involves creating a files in temporary dir and running a system command against them. On my machine it can be as much as 300x slower than a regular assert
on simple values. Make sure to use it when it really makes sense - for example for comparing large outputs - but not for everything.
The library also provides snapshot testing functionality, which is useful for comparing complex outputs against saved references. This is particularly valuable for HTML, JSON, or other structured outputs that change infrequently but need visual inspection when they do.
defmodule EmailTemplateTest do
use ExUnit.Case
use Difftastic.SnapshotTest, dir: "test/snapshots"
test "welcome email renders correctly" do
html = EmailRenderer.render_template(:welcome, user: user)
assert_snapshot_match("welcome_email.html", html)
end
end
The first time the test runs, it will create the snapshot file. On subsequent runs, it will compare the current output with the saved snapshot, showing a visual diff using Difftastic if they don't match.
To update snapshots when the expected output intentionally changes, run:
UPDATE_SNAPSHOTS=1 mix test
This is a very early version, expect potential large changes in the future, including breaking ones. Note that this library does not use SemVer, but rather something closer to BreakVer.