RSpec: Increase readability with super_diff

When handling nested hashes the RSpec output is often hard to read. Here the gem super_diff could help.

Add super_diff to your project

  1. Add super_diff to your Gemfile:
gem 'super_diff'
  1. Require it in your spec_helper.rb
require 'super_diff/rspec' # For Rails applications you can replace this with 'super_diff/rspec-rails'
  1. Customize Show archive.org snapshot colors in spec/support/super_diff.rb
SuperDiff.configure do |config|
  config.actual_color   = :green
  config.expected_color = :red
  config.border_color   = :yellow
  config.header_color   = :yellow
end
  1. Profit

Example

Imagine you expect General Kenobi to be in level 6

{
  level_1: {
    level_2: {
      level_3: {
        level_4: {
          level_5: {
            level_6: {
              general_kenobi: 'Hello there!'
            }
          }
        }
      }
    }
  }
}

but he is actually in level 3.

Then RSpec will output the diff this way:

expected: {:level_1=>{:level_2=>{:level_3=>{:level_4=>{:level_5=>{:level_6=>{:general_kenobi=>"Hello there!"}}}}}}}
     got: {:level_1=>{:level_2=>{:level_3=>{:general_kenobi=>"Hello there!", :level_4=>{:level_5=>{:level_6=>{}}}}}}}
     
(compared using ==)
     
Diff:
@@ -1 +1 @@
-:level_1 => {:level_2=>{:level_3=>{:level_4=>{:level_5=>{:level_6=>{:general_kenobi=>"Hello there!"}}}}}},
+:level_1 => {:level_2=>{:level_3=>{:general_kenobi=>"Hello there!", :level_4=>{:level_5=>{:level_6=>{}}}}}},

With super_diff the same diff will be output like this:

Expected { level_1: { level_2: { level_3: { general_kenobi: "Hello there!", level_4: { level_5: { level_6: {} } } } } } }
   to eq { level_1: { level_2: { level_3: { level_4: { level_5: { level_6: { general_kenobi: "Hello there!" } } } } } } }
Diff:

{
  level_1: {
    level_2: {
      level_3: {
+      general_kenobi: "Hello there!",
        level_4: {
          level_5: {
            level_6: {
-             general_kenobi: "Hello there!"
            }
          }
        }
      }
    }
  }
}

Caveats

  • the output of contain_exactly will omit the specific categories
expected collection contained: [...]
  actual collection contained: [...]
    the missing elements were: [...]
      the extra elements were: [...]
Expected [...] to contain exactly "XXX"
  • ActiveRecord::Base is monkey patched by
    • super_diff/rspec-rails (includes rspec and rails)
    • super_diff/rails (includes active_record and active_support)
    • super_diff/active_record
      This means that you have to require them AFTER your environment.
  • Only super_diff/rspec will look awkward in rails applications

More Info

Florian Leinsinger