[rspec-users] Coming Soon...

David Chelimsky dchelimsky at gmail.com
Fri Feb 2 05:53:50 EST 2007


Dear spec'ers,

As many of you already know, we're gearing up for a pretty big 0.8
release of RSpec in the next couple of weeks. I'm writing in advance
because I want to give you a heads up about upcoming changes and how
they may impact your existing specs.

Two important things to note first:

1. We will provide a translator that you'll be able to use to convert
the majority of your existing specs to the new syntax before we remove
deprecated methods.
2. The syntax changes described below will be the last major changes
you'll see before a 1.0 release.

Here is the plan, though the time line is not yet clear.

== rspec-0.8.0-RC1

* Will be released within the next couple of weeks.
* Will be fully backwards compatible with 0.7.5.1.
* Will also support all of the new syntax using expectation matchers
(see below).

Because this is such a significant change, we want to do a Release
Candidate first.

== rspec-0.8.x

Between 0.8.0 and 0.9.0, there will be at least one release that will include:
* A pre-0.8 to 0.9 translator.
* Noisy deprecation warnings that will let you know what methods will
be going and what you should use instead.
* A simple means of silencing those warnings (at your own peril!)

== rspec-0.9

* Will remove all of the old syntax.

=======================================
Here are some answers to some questions that some of you may have:

== What is changing?

All of the should_xyz methods will be losing an underscore and gaining a space:

  #before
  actual.should_equal(expected)
  actual.should_not_equal(expected)

  #after
  actual.should equal(expected)
  actual.should_not equal(expected)

#equal, in this example, is a method that returns an expectation matcher,
which Ruby passes to #should, which then interacts with the matcher
to evaluate whether or not the expectation is met and report accordingly.

All args to expectation matchers will require parens, and blocks must
be expressed
using curly braces. This has to do with ambiguity of arguments and
operator precedence. Don't worry, if you do the wrong thing you'll get
a warning. More on this below.

== Why this change?

The current syntax is supported by some very clever use of
method_missing. I'm allowed to say it was clever because I didn't
write it ;). At first it seemed awesome, but we've found that it
conflicts with other frameworks that use metaprogramming techniques to
late-bind to method_missing. So we had to make a choice between
rethinking RSpec's implementation or commit to a future of monkey
patching other frameworks as they introduce new uses of
method_missing.

Using expectation matchers means that we only need to add 4 methods to Object:
#for expectation matchers
should
should_not

#for mocks/stubs
should_receive
should_not_receive

So it is much less invasive than it was before and, because we are not
using method_missing on YOUR objects, is much less conflict/error
prone.

It also supports a clear entry point to writing custom expectation
matchers, so if you have some domain-specific expectations like
"should travel_more" or "should get_a_raise", you'll have a very easy
means of doing so.

== Will there be any existing expectations that will no longer be
supported at all?

Yes, but only a few, and only related to RSpec on Rails. We will NOT
be supporting the following in the new syntax:

  controller.should_render
  controller.should_redirect_to

You will be able to use instead:

  response.should render_template
  response.should render_text
  response.should redirect_to

... but only after the action.

== For )(*&)(*'s sake, WHEN will you stop making changes like this?

Right now.

While we will not commit to 100% backwards compatibility, we on the
RSpec Development Team are as anxious for this to stabilize as you
are. We just feel that when we get to a 1.0 release we absolutely must
have an API that is solid, easy to use, stable and maintainable. We
just didn't see an end in sight to the problems we'd been seeing w/
the soon-to-be-ex-syntax, and we are very confident in this move and
its potential to fulfill those requirements.

== What's up w/ the parens and {} blocks?

Parens: When you do this:

  a.b c d

... Ruby gives you the all familiar:

  "warning: parenthesize argument(s) for future version"

If you can live w/ that, then have at it w/o the parens.

Curly braces: This has to do w/ precedence. do/end has a lower
precedence than {}, which means that in this expression:

  target.should satisfy do
  end

... the block will be passed to #should instead of #satisfy. We need
the blocks to be passed to the matcher (#satisfy in this example), so
curly braces are required. This will be enforced by RSpec. When
#should or #should_not receive a block, the spec will fail with a
warning telling you to use {} instead of do/end. So you won't have the
opportunity to simply forget.

=======================================
We're very excited about this release. I hope this email answers
most of your questions. If you have others, please
feel free, though I may punt on technical questions as many of those
will be answered by documentation in the 0.8.0-RC1 release.

Thanks for your patience with this and thanks especially to all of those
who contribute to RSpec's evolution by participating with this list and
submitting RFEs to the tracker.

Cheers,
David
on behalf of The RSpec Development Team


More information about the rspec-users mailing list