[rspec-devel] Proposal: when_it syntax

aslak hellesoy aslak.hellesoy at gmail.com
Mon Oct 6 20:58:12 EDT 2008


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
>


More information about the rspec-devel mailing list