# Exposure
TODO(Gordon) - Add badges
`Exposure` is a simple and leightweight snapshot testing library for Elixir
## Installation
This package can be installed by adding `:exposure` to your list of dependencies
in `mix.exs`:
```elixir
def deps do
[
{:exposure, "~> 0.1.0", only: :test}
]
end
```
TODO(Gordon) - test env only?
## Documentation
TODO(Gordon) - Add this
## Usage
`Exposure` is easy to use and is designed to integrate seamlessly with Elixir's
`ExUnit` module.
### Defining Snapshot Tests
Snapshot tests can be defined with the `test_snapshot` macro. This macro is
syntactically similar to the normal `test` macro and interacts with other
`ExUnit` entities in the same way.
```elixir
defmodule SampleTest do
use ExUnit.Case
import Exposure
setup_all do
%{foo: 1, bar: 2}
end
describe "Map.put/3" do
@tag :sample_tag
test_snapshot "will add a new pair to a map", ctx do
ctx
|> Map.put(:baz, 3)
|> Map.take([:foo, :bar, :baz])
end
end
end
```
### Updating Snapshot Files
Once a snapshot test is defined, a snapshot file can be generated by running the
test with the `EXPOSURE_OVERRIDE` flag set to `true`:
```bash
EXPOSURE_OVERRIDE=true mix test/sample_test.exs:12
```
`Exposure` creates a snapshot directory for each test path and a snapshot file
for each test. The snapshot directory structure mirrors the test path directory
structure. For the example snapshot test above, the command would generate a
file at the following location:
```
test/_snapshots/sample_test/test_map_put_3_will_add_a_new_pair_to_a_map.exs
```
Projects using `Exposure` can also leverage the configured `:snapshot_test_tag`
to create a custom alias for generating snapshots:
```elixir
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
aliases: ["snapshots.generate": &generate_snapshots/1],
preferred_cli_env: ["snapshots.generate": :test],
...
]
end
defp generate_snapshots(args) do
System.put_env("EXPOSURE_OVERRIDE", "true")
args = ["--only", "snapshot"] ++ args
Mix.Tasks.Test.run(args)
end
...
end
```
### Running Snapshot Tests
Once a snapshot file has been created, a snapshot test can be run in the same
way as a normal test:
```bash
mix test test/sample_test.exs:12
```
### Configuration
`Exposure` has a few few configuration options that can be set in the
application config:
```elixir
# In config/test.exs
config :exposure,
snapshot_directory: "my_snapshot_dir",
snapshot_test_tag: :my_test_tag
```
More specifically, the configuration options are:
* `:snapshot_directory` - A `t:binary/0` denoting the name of the snapshot
directory. Defaults to `_snapshots`.
* `:snapshot_test_tag` - An `t:atom/0` denoting the tag that `Exposure` uses
to differentiate snapshot tests. Defaults to `:snapshot`.
### Test Paths
`Exposure` can also be used for projects with non-traditional test paths. For
more information on how to configure multiple test paths, see the `mix test`
[docs](https://hexdocs.pm/mix/1.12/Mix.Tasks.Test.html#module-configuration).
In general, `Exposure` creates a separate snapshot directory for each test path.
The only exception is if one test path contains another. In that case, a
snapshot directory is only created in the parent path. For example, consider a
project with the following configuration:
```elixir
# In mix.exs
def project do
[
test_paths: ["test", "other_test", "other_test/dir"]
]
end
```
`Exposure` would only create two snapshot directories for the above project:
```
test/_snapshots
other_test/_snapshots
```
`Exposure` requires that all snapshot tests exist within one of the project test
paths. In conjunction with the above simplification, this constraint guarantees
a consistent snapshot file location for every test.
## Other Libraries
The `Exposure` API is heavily inspired by the
[`Snapshy`](https://github.com/DCzajkowski/snapshy) library. For the vast
majority of cases, `Snapshy` is more than sufficient. The main differences are
relatively niche:
* `Exposure` has explicit support for additional test paths.
* `Exposure` has slightly different naming rules for snapshot files.
* `Exposure` requires a snapshot to exist before running a test.
If those differences are unimportant for your project, `Snapshy` may be a better
choice.
Additionally, no discussion of snapshot testing in Elixir would be complete
without mentioning the
[`assert_value`](https://github.com/assert-value/assert_value_elixir) package.
The concept of a snapshot is handled slightly differently in `assert_value` but
the library is robust and mature and definitely worth investigating.