mcmire / super_diff

A more helpful way to view differences between complex data structures in RSpec.
https://mcmire.github.io/super_diff
MIT License
913 stars 50 forks source link

Using without RSpec? #151

Open glenjamin opened 2 years ago

glenjamin commented 2 years ago

I was writing a little rake task to compare some data in our DB to fixture files, and found this module as the best one for doing pretty printed diffs of object.

I had a little bit of trouble finding out how to produce a diff without using Rspec though - I managed to get something working using:

puts SuperDiff::Differs::Main.call(from_dump, from_db)

However this lacks headings to say which item is before/after, and doesn't give a result I can use as an exit code.

Is there a good way to use this library in a standalone mode?

mcmire commented 2 years ago

Hi @glenjamin,

I'm afraid there isn't, although there should be. If you want the same header that gets printed out under RSpec as well as an exit code, you could try something like this (the header is here, for reference):

def report_diff(expected, actual)
  diff = SuperDiff::RSpec::Differ.diff(actual, expected)

  if diff.empty?
    diff
  else
    header = SuperDiff::Helpers.style do
      header "Diff:"
      newline
      newline
      border "┌ (Key) ──────────────────────────┐"
      newline
      border "│ "
      expected "‹-› in expected, not in actual"
      border "  │"
      newline
      border "│ "
      actual "‹+› in actual, not in expected"
      border "  │"
      newline
      border "│ "
      normal "‹ › in both expected and actual"
      border "  │"
      newline
      border "└─────────────────────────────────┘"
      newline
      newline
    end

    "#{header}#{diff}"
  end
end

Now you can call report_diff on your values. If this returns an empty string, then both were the same; if not, then they weren't. You should be able to use this fact to return an exit code.

jeremygpeterson commented 1 year ago

I needed a way to use SuperDiff in production, it's a long story, but here's my approach. As a caveat, all values were stored in a json field.

initializer

require 'super_diff'

SuperDiff.configure do |config|
  config.diff_elision_enabled = true
  config.diff_elision_maximum = 3
  config.color_enabled = %w[development test].include? Rails.env
end

method used

  def snapshot_diff(expected, actual)
    return '' if expected.eql? actual

    SuperDiff::Differs::Main.call(expected, actual, omit_empty: true)
  end