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

Ruby 3.4 support? #2820

Open
voxik opened this issue Dec 16, 2024 · 1 comment
Open

Ruby 3.4 support? #2820

voxik opened this issue Dec 16, 2024 · 1 comment

Comments

@voxik
Copy link
Contributor

voxik commented Dec 16, 2024

Trying to run rspec-rails test suite against Ruby 3.4, I encounter test failures such as:

   8) be_a_new matcher #with right class and new record with composable matchers one attribute is a composable matcher fails
     Failure/Error:
       expect {
         expect(record).to be_a_new(record.class).with(
           foo: a_string_matching("bar"))
       }.to raise_error("attribute {\"foo\"=>(a string matching \"bar\")} was not set on #{record.inspect}")

       expected Exception with "attribute {\"foo\"=>(a string matching \"bar\")} was not set on #<#<Class:0x00007fe77b608208>:0x00007fe77b756c68 @attributes={foo: \"foo\", bar: \"bar\"}>", got #<RSpec::Expectations::ExpectationNotMetError: attribute {"foo" => (a string matching "bar")} was not set on #<#<Class:0x00007fe77b608208>:0x00007fe77b756c68 @attributes={foo: "foo", bar: "bar"}>> with backtrace:
         # ./spec/rspec/rails/matchers/be_a_new_spec.rb:75:in 'block (7 levels) in <top (required)>'
         # ./spec/rspec/rails/matchers/be_a_new_spec.rb:77:in 'block (6 levels) in <top (required)>'
         # ./spec/spec_helper.rb:83:in 'block (3 levels) in <top (required)>'
         # ./spec/spec_helper.rb:77:in 'block (2 levels) in <top (required)>'
     # ./spec/rspec/rails/matchers/be_a_new_spec.rb:77:in 'block (6 levels) in <top (required)>'
     # ./spec/spec_helper.rb:83:in 'block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:77:in 'block (2 levels) in <top (required)>'

The error message seems to be originating from here:

def failure_message
[].tap do |message|
unless actual.is_a?(expected) && actual.new_record?
message << "expected #{actual.inspect} to be a new #{expected.inspect}"
end
unless attributes_match?(actual)
describe_unmatched_attributes = surface_descriptions_in(unmatched_attributes)
if unmatched_attributes.size > 1
message << "attributes #{describe_unmatched_attributes.inspect} were not set on #{actual.inspect}"
else
message << "attribute #{describe_unmatched_attributes.inspect} was not set on #{actual.inspect}"
end
end
end.join(' and ')
end

Specifically the #{describe_unmatched_attributes.inspect}. Here are some details from binding.irb:

rom: /builddir/build/BUILD/rubygem-rspec-rails-7.1.0-build/rspec-rails-7.1.0/usr/share/gems/gems/rspec-rails-7.1.0/lib/rspec/rails/matchers/be_a_new.rb @ line 36 :

    31:             unless actual.is_a?(expected) && actual.new_record?
    32:               message << "expected #{actual.inspect} to be a new #{expected.inspect}"
    33:             end
    34:             unless attributes_match?(actual)
    35:               describe_unmatched_attributes = surface_descriptions_in(unmatched_attributes)
 => 36:               binding.irb
    37:               if unmatched_attributes.size > 1
    38:                 message << "attributes #{describe_unmatched_attributes.inspect} were not set on #{actual.inspect}"
    39:               else
    40:                 message << "attribute #{describe_unmatched_attributes.inspect} was not set on #{actual.inspect}"
    41:               end

irb(#<RSpec::Rails::Matchers::BeA...):001> p unmatched_attributes
{"foo" => #<RSpec::Matchers::BuiltIn::Match:0x00007fa0e04f40b0 @expected="bar", @expected_captures=nil, @matcher_name=:a_string_matching>}
=> {"foo" => #<RSpec::Matchers::BuiltIn::Match:0x00007fa0e04f40b0 @expected="bar", @expected_captures=nil, @matcher_name=:a_string_matching>}
irb(#<RSpec::Rails::Matchers::BeA...):002> p surface_descriptions_in(unmatched_attributes)
{"foo" => (a string matching "bar")}
=> {"foo" => (a string matching "bar")}
irb(#<RSpec::Rails::Matchers::BeA...):003> 

Obviously Ruby 3.4 changes the Hash formatting adding two spaces around hash rocket. The question is how to fix this. Several options:

  1. Only the test cases are adjusted
    • Just add optional spaces
    • Something more elaborated, with Hash#inspect
  2. The backward compatibility of the output is kept, therefore tests stays but the error message is formatted differently

BTW I find the hash like formatting with the brackets a bit unfortunate.

https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162

@JonRowe
Copy link
Member

JonRowe commented Dec 16, 2024

We typically add conditions around output to show the differences between Ruby versions.

voxik added a commit to voxik/rspec-rails that referenced this issue Dec 17, 2024
The fixes generally tries to leverage the native `Hash#inspect` behavior
to remove the difference between Ruby 3.4 and older Rubies output.
However, some of the case are peculiar due to `DescribableItem#inspect`
\[[2]\] formatting. These needs special casing by `RUBY_VERSION`

Fixes: rspec#2820

[1]: https://bugs.ruby-lang.org/issues/20433
[2]: https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162
voxik added a commit to voxik/rspec-rails that referenced this issue Dec 17, 2024
The fixes generally tries to leverage the native `Hash#inspect` behavior
to remove the difference between Ruby 3.4 and older Rubies output.
However, some of the case are peculiar due to `DescribableItem#inspect`
\[[2]\] formatting. These needs special casing by `RUBY_VERSION`

Fixes: rspec#2820

[1]: https://bugs.ruby-lang.org/issues/20433
[2]: https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162
voxik added a commit to voxik/rspec-rails that referenced this issue Dec 17, 2024
The fixes generally tries to leverage the native `Hash#inspect` behavior
to remove the difference between Ruby 3.4 and older Rubies output.
However, some of the case are peculiar due to `DescribableItem#inspect`
\[[2]\] formatting. These needs special casing by `RUBY_VERSION`

Fixes: rspec#2820

[1]: https://bugs.ruby-lang.org/issues/20433
[2]: https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162
voxik added a commit to voxik/rspec-rails that referenced this issue Dec 17, 2024
The fixes generally tries to leverage the native `Hash#inspect` behavior
to remove the difference between Ruby 3.4 and older Rubies output.
However, some of the case are peculiar due to `DescribableItem#inspect`
[[2]] formatting. These needs special casing by `RUBY_VERSION`

Fixes: rspec#2820

[1]: https://bugs.ruby-lang.org/issues/20433
[2]: https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162
voxik added a commit to voxik/rspec-rails that referenced this issue Dec 17, 2024
This fix keeps the new Ruby 3.4 formatting. To adjust the tests, it
generally tries to leverage the native `Hash#inspect` behavior to remove
the difference between Ruby 3.4 and older Rubies output. However, some
of the case are peculiar due to `DescribableItem#inspect` [[2]]
formatting. These needs special casing by `RUBY_VERSION`

Fixes: rspec#2820

[1]: https://bugs.ruby-lang.org/issues/20433
[2]: https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162
voxik added a commit to voxik/rspec-rails that referenced this issue Dec 18, 2024
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