Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/campezzi/ignorant
Simplify comparison of Elixir data structures by ensuring fields are present but ignoring their values.
https://github.com/campezzi/ignorant
Last synced: 3 months ago
JSON representation
Simplify comparison of Elixir data structures by ensuring fields are present but ignoring their values.
- Host: GitHub
- URL: https://github.com/campezzi/ignorant
- Owner: campezzi
- Created: 2016-08-23T11:28:20.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2016-08-25T00:48:13.000Z (over 8 years ago)
- Last Synced: 2024-07-03T22:09:31.221Z (7 months ago)
- Language: Elixir
- Size: 10.7 KB
- Stars: 14
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- freaking_awesome_elixir - Elixir - Partial `Map` comparison that ensures fields are present while ignoring their values. (Testing)
- fucking-awesome-elixir - ignorant - Partial `Map` comparison that ensures fields are present while ignoring their values. (Testing)
- awesome-elixir - ignorant - Partial `Map` comparison that ensures fields are present while ignoring their values. (Testing)
README
# Ignorant
Because sometimes ignorance is bliss.
Ignorant defines a protocol for data structures that may selectively ignore specific values they
contain, usually to simplify partial comparison in tests.## Motivation
Sometimes it's useful to compare data structures in tests while ignoring pieces of data that are not
deterministic - auto-generated primary keys, calculated timestamps, and so on. Ignoring certain bits
ensures the _shape_ of the data is correct when it's not possible to enforce its values.## Example
An implementation for `Map` is provided with that package for the purpose described above. Suppose
you have an API endpoint that fetches a record from the database and returns JSON data which
translates to this `response` map:```elixir
%{
id: 37,
name: "Jim"
}
```Now let's say you want to write a test to ensure that it returns the right data. Problem is, the
`id` field is auto-generated and therefore has no deterministic value between test runs. You could
use pattern matching...```elixir%{a}
assert %{id: _, name: "Jim"} = response
```...but you can't assign the value on the left side to a variable (or module attribute) and reuse it,
and if the match fails you don't get a nice diff message. That's where `Ignorant` comes in:```elixir
assert %{id: :ignored, name: "Jim"} == Ignorant.ignore(response, [:id])
```The left side is now a proper value that can be put in a variable or attribute and reused. Also note
the `==` (equality) assertion instead of `=` (match) assertion. That gives us a pretty diff that
highlights exactly what doesn't look the same on both sides, and is also stricter (which is a good
idea in tests).It quickly becomes annoying and error-prone to tag things as `:ignored` in one side of the
comparison and include the corresponding field on the second parameter in the call to `ignore/2` on
the other side, so we can clean that up by using `merge_ignored/2`:```elixir
expected = %{id: :ignored, name: "Jim"}
assert expected == Ignorant.merge_ignored(response, expected)
````merge_ignored/2` will walk through the `expected` map extracting all fields tagged as `:ignored`, and
then apply those to `response` while keeping all other values intact. The resulting map should be
equal to `expected`. If not, you'll get a pretty diff explaining what's different.## Installation
1. Add `ignorant` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[{:ignorant, "~> 0.1.0"}]
end
```2. Ensure `ignorant` is started before your application:
```elixir
def application do
[applications: [:ignorant]]
end
```