RSpec custom legible connector

I have a special matcher in RSpec that ignores spaces / newlines and just matches the contents:

RSpec::Matchers.define :be_matching_content do |expected| match do |actual| actual.gsub(/\s/,'').should == expected.gsub(/\s/,'') end diffable end 

I can use it like this:

  body = " some data \n more data" body.should be_matching_content("some data\nmore wrong data") 

However, when the test fails (e.g. above), the diff output does not look very good:

  -some data -more wrong data + some data + more data 

Can dynamic output be configured? The first row of some data correct, but the second more wrong data is incorrect. It would be very helpful to get the second row as the main reason for the failure.

+6
source share
3 answers

I believe that you should disable the default diffable in RSpec and replace your own implementation:

 RSpec::Matchers.define :be_matching_content do |expected| match do |actual| @stripped_actual = actual.gsub(/\s/,'') @stripped_expected = expected.gsub(/\s/,'') expect(@stripped_actual).to eq @stripped_expected end failure_message do |actual| message = "expected that #{@stripped_actual} would match #{@stripped_expected}" message += "\nDiff:" + differ.diff_as_string(@stripped_actual, @stripped_expected) message end def differ RSpec::Support::Differ.new( :object_preparer => lambda { |object| RSpec::Matchers::Composable.surface_descriptions_in(object) }, :color => RSpec::Matchers.configuration.color? ) end end RSpec.describe 'something'do it 'should diff correctly' do body = " some data \n more data" expect(body).to be_matching_content("some data\nmore wrong data") end end 

produces the following:

 Failures: 1) something should diff correctly Failure/Error: expect(body).to be_matching_content("some data\nmore wrong data") expected that somedatamoredata would match somedatamorewrongdata Diff: @@ -1,2 +1,2 @@ -somedatamorewrongdata +somedatamoredata 

You can use custom differences, if you want, to even override this entire connector with the diff command system call, something like this:

 ♥ diff -uw --label expected --label actual <(echo " some data \n more data") <(echo "some data\nmore wrong data") --- expected +++ actual @@ -1,2 +1,2 @@ some data - more data +more wrong data 

Hooray!

+8
source

You can override the expected and actual methods, which will then be used to create the diff. In this example, we store the expected and actual values ​​as instance variables and define methods that return instance variables:

 RSpec::Matchers.define :be_matching_content do |expected_raw| match do |actual_raw| @actual = actual_raw.gsub(/\s/,'') @expected = expected_raw.gsub(/\s/,'') expect(expected).to eq(@actual) end diffable attr_reader :actual, :expected end 

Another example is matching specific attributes in two different types of objects. (The expected object in this case is the Client model.)

 RSpec::Matchers.define :have_attributes_of_v1_client do |expected_client| match do |actual_object| @expected = client_attributes(expected_client) @actual = actual_object.attributes expect(actual_object).to have_attributes(@expected) end diffable attr_reader :actual, :expected def failure_message "expected attributes of a V1 Client view row, but they do not match" end def client_attributes(client) { "id" => client.id, "client_type" => client.client_type.name, "username" => client.username, "active" => client.active?, } end end 

An example error is as follows:

 Failure/Error: is_expected.to have_attributes_of_v1_client(client_active_partner) expected attributes of a V1 Client view row, but they do not match Diff: @@ -1,6 +1,6 @@ "active" => true, -"client_type" => #<ClientType id: 2, name: "ContentPartner">, +"client_type" => "ContentPartner", "id" => 11, 
+4
source

There is a gem called diffy that you can use.

But it goes line by line and compares them, so instead of removing all spaces, you can replace any number of spaces with a newline and distinguish between these entries.

This is an example of what you could do to improve your differences a bit. I'm not 100% sure where to paste this into your code.

 def compare(str1, str2) str1 = break_string(str1) str2 = break_string(str2) return true if str1 == str2 puts Diffy::Diff.new(str1, str2).to_s return false end def break_string(str) str.gsub(/\s+/,"\n") end 

Differential pearls can be configured to obtain a color output suitable for the terminal.

Using this code will work as follows

 str1 = 'extra some content' str2 = 'extra more content' puts compare(str1, str2) 

it will print

  extra -some # red in terminal +more # green in terminal content \ No newline at end of file 
+1
source

All Articles