The End of Assertion Gobbledygook

Burdette Lamar - Sep 8 '18 - - Dev Community

I'm working on a new Ruby gem minitest_lucid that improves the error output from minitest assertions.

For testing Ruby hashes:

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

Not So Good

Here's what you get from a failed assert_equal 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."}
Enter fullscreen mode Exit fullscreen mode

Better

Here's what you get if you add make_my_diffs_pretty! 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."}

Enter fullscreen mode Exit fullscreen mode

Best

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

  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'
Enter fullscreen mode Exit fullscreen mode

For the Record

Here's the actual test:

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
Enter fullscreen mode Exit fullscreen mode

Implementation

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

Scope

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

  • Hash
  • Array
  • Set
  • Struct
  • Openstruct

Questions

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 diff-lcs 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?

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .