The End of Assertion Gobbledygook
Tags: ruby, testing, opensource
Published: 2018-09-08 14:59:41

---
title: The End of Assertion Gobbledygook
published: true
description: Lucid error messages for minitest assertions.
tags: ruby, testing, opensource
---
I'm working on a new Ruby gem <code>minitest_lucid</code> that improves the error output from <code>minitest</code> assertions.


For testing Ruby hashes:

- **Not so good**:  default <code>assert_equal</code> behavior can produce a messy result.
- **Better**:  same assertion, but with added call to <code>make_my_diffs_pretty!</code> (actually part of <code>minitest</code> itself), produces a better result.
- **Best**:  same assertion, but with added <code>require 'minitest_lucid'</code> (the forthcoming gem), produces the best result.


<h3>Not So Good</h3>

Here's what you get from a failed <code>assert_equal</code> for two hashes, each with eight entries:

```
  1) Failure:
MinitestLucidTest#test_hash [C:/Users/Burdette/Documents/GitHub/minitest_lucid/test/minitest_lucid_test.rb:28]:
--- expected
+++ actual
@@ -1 +1 @@
-{:tauro=>"Cia ina do ip ocat doat.", :loquens=>"Dua sarat rad noad maat caea.", :lor=>"Eser in dolo eaata labor ut.", :dolo=>"Ipaat paal doat iruat ala magabor.", :offab=>"Ut dolore ua consal vaba caea.", :moam=>"Sunt sed te coma teu alaaame."}
+{:laboru=>"Laboab vaga dat maaua in venima.", :dolo=>"Ipaat paal doat iruat ala magabor.", :loquens=>"dua sarat rad noad maat caea.", :lor=>"Eser in dolo eaata labor ut.", :tauro=>"cia ina do ip ocat doat.", :amcae=>"Utatu cilaa cit siat commag seqa."}
```

<h3>Better</h3>

Here's what you get if you add <code>make_my_diffs_pretty!</code> to your test:

```
  1) Failure:
MinitestLucidTest#test_hash [C:/Users/Burdette/Documents/GitHub/minitest_lucid/test/minitest_lucid_test.rb:28]:
--- expected
+++ actual
@@ -1,6 +1,6 @@
-{:tauro=>"Cia ina do ip ocat doat.",
- :loquens=>"Dua sarat rad noad maat caea.",
- :lor=>"Eser in dolo eaata labor ut.",
+{:laboru=>"Laboab vaga dat maaua in venima.",
  :dolo=>"Ipaat paal doat iruat ala magabor.",
- :offab=>"Ut dolore ua consal vaba caea.",
- :moam=>"Sunt sed te coma teu alaaame."}
+ :loquens=>"dua sarat rad noad maat caea.",
+ :lor=>"Eser in dolo eaata labor ut.",
+ :tauro=>"cia ina do ip ocat doat.",
+ :amcae=>"Utatu cilaa cit siat commag seqa."}

```

<h3>Best</h3>

And here's what you get from <code>minitest_lucid</code> if you add <code>require minitest_lucid</code> to your test:

```ruby
  1) Error:
MinitestLucidTest#test_hash:
Exception:
elucidation = {
    :missing_pairs => {
      :offab => 'Ut dolore ua consal vaba caea.',
      :moam => 'Sunt sed te coma teu alaaame.',
    },
    :unexpected_pairs => {
      :laboru => 'Laboab vaga dat maaua in venima.',
      :amcae => 'Utatu cilaa cit siat commag seqa.',
    },
    :changed_values => {
      :tauro => {
        :expected => 'Cia ina do ip ocat doat.',
        :got      => 'cia ina do ip ocat doat.',
      },
      :loquens => {
        :expected => 'Dua sarat rad noad maat caea.',
        :got      => 'dua sarat rad noad maat caea.',
      },
    },
    :ok_pairs => {
      :lor => 'Eser in dolo eaata labor ut.',
      :dolo => 'Ipaat paal doat iruat ala magabor.',
    },
}
    C:/Users/Burdette/Documents/GitHub/minitest_lucid/test/minitest_lucid_test.rb:28:in `test_hash'
```

<h3>For the Record</h3>

Here's the actual test:

```ruby
require 'minitest_lucid'

class MinitestLucidTest < Minitest::Test

  def test_hash
    expected = {
        :tauro => 'Cia ina do ip ocat doat.',
        :loquens => 'Dua sarat rad noad maat caea.',
        :lor => 'Eser in dolo eaata labor ut.',
        :dolo => 'Ipaat paal doat iruat ala magabor.',
        :offab => 'Ut dolore ua consal vaba caea.',
        :moam => 'Sunt sed te coma teu alaaame.',
    }
    actual = {
        :laboru => 'Laboab vaga dat maaua in venima.',
        :dolo => 'Ipaat paal doat iruat ala magabor.',
        :loquens => 'dua sarat rad noad maat caea.',
        :lor => 'Eser in dolo eaata labor ut.',
        :tauro => 'cia ina do ip ocat doat.',
        :amcae => 'Utatu cilaa cit siat commag seqa.',
    }
    assert_equal(expected, actual)
  end

end
```

<h3>Implementation</h3>

The **only** change to test code needed is to <code>require 'minitest_lucid'</code> (after, of course, installing the gem once it's released).

<h3>Scope</h3>

I'm expecting the new gem to treat all collections in the Ruby core and standard libraries:

- <code>Hash</code>
- <code>Array</code>
- <code>Set</code>
- <code>Struct</code>
- <code>Openstruct</code>

<h3>Questions</h3>

Please feel free to opine:

- Is there a better name for the gem?  I definitely want the name to include the word *minitest*;  it *could* include the word *assertions*, but then it would need a third word to indicate what the gem does.

- I'm thinking to use gem <code>diff-lcs</code> for arrays, because it can identify similar but out-of-position sequences.  Should there be an option to just do a straight-up slot-for-slot comparison?

- Are there other collections that should be considered?

- Are there scalars (non-collections) whose messages deserve improvement?