rspec/rspec-expectations — pull request #119 by myronmarston (2012-03-04 07:32:55+00:00)
Title: Add support for `expect(value)` syntax.

Note: I'm opening this pull request just to start a discussion about this. It's not ready to be merged yet.

### Feature Summary

This adds an alternate syntax to the existing `should` syntax for setting expectations. It's based on the already existing use of `expect` for block expectations but makes it work for normal ones, too:

``` ruby
expect(something).to be_awesome
# rather than:
something.should be_awesome
```

I've already had a few conversions with @dchelimsky and @justinko about this. There are some details we need to work out and I also want to get feedback from a wider base of RSpec users.

Here's a summary of why I think this new syntax has value:

1. Currently, there are two syntaxes for setting expectations: `should` for normal expectations, and `expect` for block expectations (or you can fall back to using a lambda/proc). This unifies them: you can use expect for both.
2. This also aligns the syntax with Jasmine, which can be nice for people working on projects that use both.
3. I believe that all matchers will work just fine with this new syntax.
4. This opens up the possibility of not monkey patching every object in the system with `should` and `should_not`.
5. `should` and `should_not` are prone to problems related to the fact that any object can undefine or redefine them on itself and it suddenly can break rspec-expectations. We've actually seen a few cases of this (where it was completely unintentional, in fact!). Consider the case of a proxy object that uses `BasicObject`, defines a method (`proxy_method`) and proxies the rest to a target object using `method_missing`. An expectation like `proxy.should respond_to(:proxy_method)` can wrongly fail, because `should` will be proxied through to the target object, so this winds up being `target.should respond_to(:proxy_method)`. In contrast, `expect(proxy).to respond_to(:proxy_method)` would work just fine. For some more cases of problems like these, see #114, rspec/rspec-core#471 and rspec/rspec-rails#445.

The last one is the biggie for me. I've been bitten by weird, hard-to-track-down bugs with `should` on delegate objects.

### Open Questions

So, open questions for discussion:

1. Is anyone against adding this as an alternate syntax to rspec-expecations?
2. Does it makes sense to provide a way for someone to use rspec-expectations w/o `should` and `should_not` being monkey-patched onto `Kernel`? The value I see here is that if people decide that `expect` is the preferred syntax for a given project, it would be nice to be able to help enforce uniformity by preventing `should` and `should_not` from being used (which, in turn, would ensure the project never has any of the weird proxy-object `should` issues we have seen). Note that I wouldn't consider every removing `should` and `should_not` from rspec-expectations entirely. There's too much code out in the wild that uses and it generally works fine.
3. If we do want to provide a way to disable `should`/`should_not`, what should that mechanism be?
4. If we decide to provide the means, and decide that `expect` is the preferred syntax, would it make sense to disable `should` and `should_not` by default in some future major release (i.e. make it opt-in for that syntax, rather than opt-out).

### My Two Cents

I like this syntax a lot (obviously; that's why I opened this PR!), and I'd like a way to be able to disable `should` and `should_not` on future projects. I'm not yet sure what that way should be, but one possibility is the existing `expect_with` option in rspec-core. Maybe it could support `expect_with :rspec` for all of rspec-expectations, and `expect_with :rspec_only_expect` (or something better named) for rspec-expectations w/o `should`. As for #4: if rspec users like the `expect` syntax, and we can ensure a smooth transition, and provide could deprecation messages, I'd probably be in favor of disabling `should` by default in 3.0 or 4.0, simply because it avoids a whole class of issues.

If you're an RSpec user and you have any opinion on this whatsoever, please leave a comment!