-
-
Notifications
You must be signed in to change notification settings - Fork 395
is_expected with block expectations #805
Comments
Not with the one liner syntax that I'm aware of.
It's in the same bucket, I certainly don't recommend it.
We should mention they're not supported.
this has come up before and we shied away from it because the only way to really do it is to pass a block out of the subject block and then conditionally detect what to do with it, the last conversation we had around this resulted in the original issue raiser producing https://github.com/puyo/rspec-subject_call |
There is, if you're willing to make your describe 'is_expected with block expectation' do
subject { -> { raise } }
it { is_expected.to raise_error }
end ...that's pretty obtuse and not something I'd recommend, generally.
I consider it in between. It's not something I use frequently, and it's an often abused feature of RSpec...but it's not generally problematic the way
Agreed.
I think the complexity to doing such a thing would be greater than the benefit. I also think it's good for people to understand that the expectation is being set on a lambda/proc that wraps an expression, and not on the return value of the expression itself. Any attempt to make this work nicely would hide that distinction which would only lead to more confusion. Also, you'll generally get warnings from RSpec 3 when you attempt to use a block matcher against a non-block subject. That falls over for |
For the mustermann-style case, I tend to use a custom method: https://github.com/xaviershay/pacebot/blob/master/spec/parse_spec.rb#L23 ... but then I'm the kind of heathen that tends to like I'll put together a doc PR. |
😱 |
I obviously haven't done this. I may still, but am relaxing the commitment expressed in my prior comment. |
if is_expected would be defined as def is_expected
expect { subject }
end ( using { } instead of ( )) then it should work. Also will help with But it could slow down a little every is_expected call. Any other reasons, why it wasn't done in that way? |
The reason is that
See #526 for more background and info on this. |
@xaviershay and @myronmarston what's the status of this issue? |
The consensus is to improve the documentation around this but no one has taken that on yet. Would you like to? |
yup @myronmarston I'll do that during this upcoming week |
I think we can close this PR as the docs around the one-liner syntax has been improved |
Could maybe add a |
I don't think it reads well but if you want to add it to a project (or build a gem that provides it), it's trivial: module IsExpectedBlock
def is_expected_block
expect { subject }
end
end
RSpec.configure do |c|
c.include IsExpectedBlock
end |
@myronmarston I basically ended up doing the same thing in a project, but I named it |
Since it's related to exceptions it could be something like def is_expected_to_raise(*args)
expect { subject }.to raise_exception(*args)
end
# and use it like
it { is_expected_to_raise SomeError, 'error message' }` Even though I think naming the subject will produce very expressive sentence too. describe '#some_method' do
subject(:some_method) { described_class.new(...).some_method(invalid_args) }
it { expect { some_method }.to raise_exception(SomeError, 'error message') }
end |
@guih that is certainly a way to do it, but I still don't feel it warrants being included in the main gems, as you've demonstrated it's easy enough to customise your own install when needed |
Thanks for answering @JonRowe 😃 Sorry, I expressed myself badly in the previous comment. I was not intended to have this included to the main gem, I was just trying to show that sometimes it's more expressive without it as an argument not to include it. |
I've decided to use this in my project:
and in spec:
|
moved #singleton to BasicObject changed title in README.md added short circuit for bad year/day combinations added tests for 404 using let instead of begin created with_block_is_expected rspec/rspec-expectations#805 (comment)
I ended up calling it "anticipation". Compared to an "expectation" it describes the expectation of a future state more explicitly in my eyes (english native speakers please correct me).
Using the following configuration:
|
@schmijos Jon recently mentioned This approach has some downsides not directly related to testing. What would be the benefit compared to more explicit:
or
? |
@pirj Thank you for summing up the references. The downsides seem plausible to me. But I see myself often use the one-liner syntax and it just bugs me a lot to break the consistency of a test block because I seem to like the kind of this pattern: describe '#do_something' do
subject { instance.do_something }
it { is_expected.to be_successful }
it { is_expected.to have_attributes(blub: …) }
it { is_expected.to change { sut } }
it { is_expected.to make(sut).receive(:request) }
… For me this reads a lot more like a specification list than what we're doing with |
I had an idea of a
There are some questions I have to this code though. Both Are you a strong proponent of "one expectation per example"? With the introduction of
Do you have an implementation of You may expect to see proper documentation output from this, and if something fails, even if it's just one expectation, it can be distinguished from the met expectations. |
Users sometimes try to use the one-liner syntax with block matchers, which can cause RSpec to behave in strange ways. This behaviour is not supported in RSpec because the complexity of implementing it would greatly outweigh the benefits. This commit just clarifies in the documentation that the one-liner syntax does not support block matchers. Possible fix for rspec/rspec-expectations#805
This is how I got around it: # spec_helper.rb
RSpec.configure do |config|
config.include(Module.new { def is_expected_in_block = expect { subject } })
end # rubocop.yml
RSpec/NoExpectationExample:
AllowedPatterns:
- is_expected_in_block |
The following situation just confused someone here at work:
That reads like it should work, but doesn't because
is_expected
is defined asexpect(subject)
.I don't typically use
is_expected
, so not sure if there is a canonical way to do this already. It isn't listed at https://www.relishapp.com/rspec/rspec-core/docs/subject/one-liner-syntaxexpect_any_instance_of
bucket of extras?is_expected
implementation based on matcher used and that seems gnarly.Tangentially related discussion thread on separating block vs value expectations, in which we didn't discuss this case: #526
cc @rspec/rspec
The text was updated successfully, but these errors were encountered: