rspec-expectations
rspec-expectations copied to clipboard
Compound failure messages with more than 2 matchers are wrongly indented
Running the following spec:
describe 'compound expectation' do
context 'with 2 matchers' do
it 'indents the messages properly' do
expect { :nothing }
.to change { @foo }
.and change { @bar }
end
end
context 'with 3 matchers' do
it 'indents the messages wrongly' do
expect { :nothing }
.to change { @foo }
.and change { @bar }
.and change { @baz }
end
end
end
... outputs the following messages:
Failures:
1) compound expectation with 2 matchers indents the messages properly
Failure/Error:
expect { :nothing }
.to change { @foo }
.and change { @bar }
expected result to have changed, but is still nil
...and:
expected result to have changed, but is still nil
# ./spec/test_spec.rb:4:in `block (3 levels) in <top (required)>'
2) compound expectation with 3 matchers indents the messages wrongly
Failure/Error:
expect { :nothing }
.to change { @foo }
.and change { @bar }
.and change { @baz }
expected result to have changed, but is still nil
...and:
expected result to have changed, but is still nil
...and:
expected result to have changed, but is still nil
# ./spec/test_spec.rb:12:in `block (3 levels) in <top (required)>'
Finished in 0.02502 seconds (files took 0.13832 seconds to load)
2 examples, 2 failures
This is working as designed. The nesting intentionally mirrors the grouping. In the expression:
expect { :nothing }
.to change { @foo }
.and change { @bar }
.and change { @baz }
...the ordering of ruby's evaluation causes this equivalent to be created:
Compound::And.new(
Change.new { @foo },
Compound::And.new(
Change.new { @bar },
Change.new { @baz }
)
)
...and the failure output mirrors that structure. Now, in the case of just and or just or, it's associative, so that A & (B & C) and (A & B) & C are equivalent (and some with the ||). So we could flatten the failure output for these cases.
But if you're mixing and and or:
expect { :nothing }
.to change { @foo }
.and(change { @bar }
.or change { @baz })
or:
expect { :nothing }
.to (change { @foo }
.and change { @bar })
.or change { @baz }
...then it's not associative, the grouping very much matters, and I think it's important that the failure output mirrors the structure.
There might be a simple way to get the flattened output for when the user is using all and or all or, but for the general case I think we need to keep the nested output format.
...then it's not associative, the grouping very much matters, and I think it's important that the failure output mirrors the structure.
That makes sense.
There might be a simple way to get the flattened output for when the user is using all and or all or, but for the general case I think we need to keep the nested output format.
:+1:
Close?
There might be a simple way to get the flattened output for when the user is using all
andor allor
I think I will try implementing this.
Closing due to inactivity during the monorepo migration