[rspec-devel] Proposal: when_it syntax

Zach Dennis zach.dennis at gmail.com
Sun Oct 5 10:54:31 EDT 2008


On Sun, Oct 5, 2008 at 5: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?
>

I don't think it does.  Here's why IMO:

* "when_it do" reads horribly. Just read it outloud, it sounds wrong.
* The word :implicitly that may get appended is a noise word. It is
not apparent what it does, and it cannot be inferred. It must be
learned. It also provides no value (outside of technical detail) to a
reader of the example that body of the it block will be used before
making the method call, or after making the method call.
* Using :implicitly means the body of an it block does one of two
things. For developers this means that they must  always keep the
context of how the it block will be run when reading the example, or
writing new ones.
* when_it can't be used across the board, and nor should it, because
it separates the call to execute the behaviour from any important
pre-conditions and also any post behaviour verification. These things
should be tightly bound together to make the example clear and
understandable to readers of the code.

When I say pre-conditions I'm not just talking about what goes in a
before block. I'm talking about communicating to the reader so they
don't have to go scrolling up to a before block (let alone up through
several before blocks). For instance:

it "finds the most recent project by year" do
   Project.should_receive(:project_by_year).with("1999")
   get :show, :year => "1999"
end

it "assigns :project" do
   Project.stub!(:project_by_year).and_return "project"
   get :show
   assigns[:project].should == "project"
end

Even if a before block stubbed out Project.project_by_year to return a
project, in the assigns example, I want to explicitly tell the reader
of the example what it is being assigned to. It doesn't appear that
you can do this "assigns" example with when_it.


-- 
Zach Dennis
http://www.continuousthinking.com
http://www.mutuallyhuman.com


More information about the rspec-devel mailing list