Chain expectations but abort on first failing

15 views
Skip to first unread message

Nick Sutterer

unread,
Jan 2, 2022, 12:18:01 PM1/2/22
to rspec
Currently, we have a matcher `assert_pass` that internally combines two matchers as follows.

```ruby
def pass_with(args)
  pass.and _pass_with(args) # TODO: abort when {pass} fails
end
```

What we need, though, is to have `pass` abort if it fails, and not run `_pass_with`. Presently, both matchers are run regardless of which one fails. Is it possible to do so? 

Many thanks in advance and best wishes for 2022,

Nick

Phil Pirozhkov

unread,
Jan 3, 2022, 2:50:31 PM1/3/22
to Jack Royal-Gordon
Hi Nick,

The trick is that `_pass_with` actually runs first, and when it runs `actual.call`, it calls `pass`.
What you can do is to skip the check in `pass` if `actual.call` returns `false`, i.e. `pass` failed matching.

All the best in 2022!

- Phil

--
You received this message because you are subscribed to the Google Groups "rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rspec+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/ecdfcced-840c-49e4-9095-22c1ebd510f6n%40googlegroups.com.

Jon Rowe

unread,
Jan 6, 2022, 11:35:01 AM1/6/22
to rspec
I accidentally sent a private reply rather than a public one, and the exact text escapes me, but the TL;DR of that reply is both sides are executed in order to produce better failure output, roughly what I replied to nick was that:

```Ruby
expect(thing).to pass.and pass_with(...)
```

produces:

```
     Failure/Error: expect(thing).to pass().and pass_with(...)

          expected thing to pass

       ...and:

          expected thing to pass_with ...
```

So if you want to short circuit, you can execute them sequentially,

```Ruby
expect(thing).to pass
expect(thing).to pass_with(...)
```

This might not make much sense with this contrived example, but its intent when introduced was to allow specs to make multiple assertions about a thing, and have that failure output.

Consider an "expensive" acceptance test like:

```Ruby
expect(html).to have_header("My article title").and have_content("My article text")
```

It's obviously much better to see either failure or both when the test fails than to re run the test to see the second failure after fixing the first...

Cheers (and apologies to Nick as he'll receive this twice :))
Jon
Reply all
Reply to author
Forward
0 new messages