Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

have_attributes matcher shows confusing results for BigDecimal values #1064

Closed
JunichiIto opened this issue Jul 1, 2018 · 2 comments
Closed

Comments

@JunichiIto
Copy link

Subject of the issue

have_attributes matcher shows confusing results for BigDecimal values.

Your environment

  • Ruby version: ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
  • rspec-expectations version: 3.7.0

Steps to reproduce

Save the following code as sample_spec.rb:

class Point
  attr_reader :name, :x, :y
  def initialize(name, x, y)
    @name = name
    @x = x
    @y = y
  end
end

require 'bigdecimal'
describe Point do
  example do
    point = Point.new('foo', BigDecimal('1.23'), BigDecimal('4.56'))
    expect(point).to have_attributes(
      name: 'bar',
      x: 1.23,
      y: 4.56
    )
  end
end

Run the script:

rspec sample_spec.rb

Expected behavior

In this case, only the value of name is different, so it should show x and y are OK:

-:name => "bar",
+:name => "foo",
 :x => 1.23,
 :y => 4.56,

Actual behavior

But it shows as if x and y were also different, and their format seems exponential notation:

-:name => "bar",
-:x => 1.23,
-:y => 4.56,
+:name => "foo",
+:x => 0.123e1,
+:y => 0.456e1,

This behavior is very confusing because the spec will pass when the value of name is changed to 'foo' (No need to change x and y). And it is very difficult to tell 1.23 and 0.123e1 are same or different.

@myronmarston
Copy link
Member

Thanks for reporting this, @JunichiIto!

I agree this is confusing behavior. However, it's not specific to have_attributes: it's a general problem with any matcher that produces a diff. RSpec produces a diff by converting the expected and actual values to strings (generally using #inspect) and then running those through diff-lcs to get the diff. This was a pretty good, low-cost way for RSpec to start providing diffs years ago but only works as well as the string output for matching values is exactly equivalent. In this case, 1.23 and BigDecimal(1.23) correctly match, but produce different string output and therefore show up as a difference in the diff.

We are aware of this issue and work has started on prototyping a replacement for RSpec's current differ. Once we improve the differ to be more aware of RSpec's matching semantics, and not simply do a string diff, this problem will be fixed for have_attributes and every other matcher that uses diffing.

I'm going to close as there's nothing actionable for us to do directly related to the have_attributes matcher and we've begun work on a potential solution.

@JunichiIto
Copy link
Author

@myronmarston Thank you for reply. I understand the background of this problem. I am looking forward to the improvement of the diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants