[rspec-devel] Proposal: when_it syntax

Yehuda Katz wycats at gmail.com
Mon Oct 6 21:06:10 EDT 2008


My goal here is to try to get people comfortable with black-box testing.
Unfortunately, every fewer ounce of syntactic sugar is an impediment to
convincing people to do the right thing.
This is somewhat similar, imho, to the argument about test/unit syntax vs.
rspec syntax.

Is foo.should == bar really much better than assert_equal(foo, bar)? And
think about the magic required to implement it!

-- Yehuda

On Mon, Oct 6, 2008 at 5:58 PM, aslak hellesoy <aslak.hellesoy at gmail.com>wrote:

> On Sun, Oct 5, 2008 at 5:10 PM, David Chelimsky <dchelimsky at gmail.com>
> wrote:
> > On Sun, Oct 5, 2008 at 4:23 AM, Antti Tarvainen <antti.tarvainen at iki.fi>
> wrote:
> >> Hello.
> >>
> >>
> >> I propose a new syntax that helps DRY up specs when using
> >> one-expectation-per-example style. There have been similar proposals
> >> before, but no patches. As far as I know, the idea wasn't killed, just
> >> forgotten.
> >>
> >> The patch adds a new "when_it" method and a new parameter to the "it"
> >> method. "When_it" describes the action of the example, allowing "it"
> >> parts to describe only the expectation.
> >>
> >> The new parameter to "it" is called :implicitly, and it means that the
> >> expectation should be run before the "when_it" part. (That is, it is a
> >> mock expectation, and regards the implicit interface of the object.)
> >> "It" parts without the :implicitly parameter are run after the
> >> "when_it" part.
> >>
> >>
> >> Here's an example of the syntax:
> >>
> >> describe Controller do
> >>  before(:each) do
> >>    @model = mock("model").as_null_object
> >>    @view = mock("view").as_null_object
> >>    @controller = Controller.new(@model, @view)
> >>  end
> >>
> >>  when_it do
> >>    @return_value = @controller.act_on(:some_input)
> >>  end
> >>
> >>  it "should get data from model", :implicitly do
> >>    @model.should_receive(:data_for).with(:some_input)
> >>  end
> >>
> >>  it "should return :success" do
> >>    @return_value.should == :success
> >>  end
> >> end
> >>
> >>
> >> For a slightly longer example, see http://tinyurl.com/when-it-example .
> >>
> >> What do you think? The new syntax makes specs more DRY, but does it
> >> improve readability?
> >
> > To be honest, I think this really hurts readability. First,
> > :implicitly doesn't really say what it means, which is "the implicit
> > action should happen after the code in this block".
> >
> > Second, the fact that the action happens before some actions in the
> > group and after others is going to be confusing when trying to
> > understand a failure.
> >
> > Ironically, Yehuda Katz is in the middle of working on a patch that
> > supports something very similar, though it doesn't handle the
> > before/after action choice: http://gist.github.com/14670
> >
> > Here's what I'm thinking. Rather than loading up rspec with new stuff
> > like this that I'm personally skeptical about, what I'd rather do is
> > expose a legitimate extension point that would allow you to do exactly
> > what you're trying to do and the same for yehuda. Something like this:
> >
> > Spec::Runner.configure do |config|
> >  config.extend_example do |example|
> >    # access to a wrapper for the example
> >    # that exposes its args hash and other
> >    # useful stuff
> >  end
> >
> >  config.extend_example_group do |group|
> >    # access to a wrapper for the example group
> >    # that exposes its args hash and other
> >    # useful stuff
> >  end
> > end
> >
> > Then you could (theoretically) do stuff like this:
> >
> > GIVENS = {}
> >
> > def given(name, &block)
> >  GIVENS[name] = block
> > end
> >
> > given "logged in" do
> >  login
> > end
> >
> > Spec::Runner.configure do |config|
> >  config.extend_example do |example|
> >    if example.args[:given]
> >      example.before &GIVENS[args[:given]]
> >    end
> >  end
> > end
> >
> > That's a quick and dirty implementation (and may or may not work as
> > written ;) ), but just to show you the sort of power you'd have.
> >
> > Maybe there's a better way, but WDYT, in general, about the idea of
> > having some sort of official extension points for Examples and
> > ExampleGroups that would make it easy for people to write (and
> > publish) their own extensions without fear of rspec breaking them
> > later?
> >
>
> I'm probably missing something here, but it seems to me that Antti and
> Yehuda's examples can be simply written with #before or regular method
> defs:
>
> http://gist.github.com/15198 (Yehuda's original is
> http://gist.github.com/14670)
> http://gist.github.com/15199 (Antti's original higher up in this thread)
>
> While I agree we need a better extension API, I don't see why it's
> needed in the cases presented here. Too much magic - we already have
> simpler constructs to do the same.
>
> Aslak
>
> > David
> >
> >>
> >>
> >> [patch]
> >> http://github.com/tarvaina/rspec/commits/topic/when_it_in_one_commit
> >>
> http://github.com/tarvaina/rspec-rails/commits/topic/when_it_compatibility
> >>
> >> [one expectation per example]
> >>
> http://techblog.daveastels.com/2006/08/27/one-expectation-per-example-a-remake-of-one-assertion-per-test/
> >>
> >> [old discussions]
> >>
> http://rubyforge.org/tracker/?func=detail&group_id=797&aid=10285&atid=3152
> >> http://rubyforge.org/pipermail/rspec-users/2007-April/001386.html
> >>
> >>
> >> Antti
> >> _______________________________________________
> >> rspec-devel mailing list
> >> rspec-devel at rubyforge.org
> >> http://rubyforge.org/mailman/listinfo/rspec-devel
> >>
> > _______________________________________________
> > rspec-devel mailing list
> > rspec-devel at rubyforge.org
> > http://rubyforge.org/mailman/listinfo/rspec-devel
> >
> _______________________________________________
> rspec-devel mailing list
> rspec-devel at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-devel
>



-- 
Yehuda Katz
Developer | Engine Yard
(ph) 718.877.1325
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-devel/attachments/20081006/2a3fcc14/attachment-0001.html>


More information about the rspec-devel mailing list