On Sun, Dec 16, 2012 at 3:07 AM, Perry Smith <[email protected]> wrote:
> Below are two methods of doing the same thing in a view spec. I have some
> hidden magic to tie in to capybara which I am not showing.
First question: why lay another abstraction on top of what is already
an abstraction for spec'ing html content?
>
> To me, the advantage of the first is if there is a failure, there will be a
> very nice error message that tells you exactly what is wrong. The downside
> of the first is it renders the template eight times instead of just once. I
> can't figure out a way around that. "render" is not available until after
> the "it" is entered. before(:all) didn't work when I tried it. The first
> form also creates beautiful documentation when --format documentation is
> used.
>
> Part of my question is this: I've heard that with unit tests, you want one
> "assert" per test. This is what the first method does.
The motivation for one expectation per example is that if the first
expectation fails, the subsequent expectations are not evaluated. This
can lead to a frustrating scenario in which you get the first
expectation to pass, only to find that the second one fails. Then you
get that one to pass only to find that the third fails, etc.
The tradeoff is that, with one expectation per example, you end up w/
more examples. Ideally you want to find a balance that gives you the
best of both worlds: as few examples as are necessary to describe the
behavior _and_ quick failure isolation when there is a failure.
You can spec that a label with specific properties should exist in a
single line w/ Capybara:
# render returns @rendered, which is also returned by the rendered method.
example { render.should have_selector("form label[for=swinfo]", :text
=> "item") }
Given that, I don't see much benefit from the extra abstraction and
redirection in the examples below. The error message could offer more
info (it only says that it couldn't find a matching selector), but it
turns out to be quite a challenge to do so in a way that works for all
situations. If you have a good way to do it, please submit a pull
request to Capybara for Jonas' consideration.
Cheers,
David
> The second method is very concise... but does not produce as nice an error
> message and rather horrible output for --format documentation
>
> I'm also curious if rigorously testing a form like this is typical. I know
> that I often screw up the forms and don't figure it out until I try to
> exercise them.
>
> describe "welcome/index.html.erb" do
> # first method
> describe "the swinfo form" do
> before(:each) do
> render
> end
>
> def form
> @form ||= rendered.find('form#swinfo_form')
> end
>
> def label
> @label ||= form.find('label')
> end
>
> def text_box
> @text_box ||= form.find('input[type="text"]')
> end
>
> it "should exist" do
> form
> end
>
> it "should have an action of /swinfos" do
> form[:action].should == '/swinfos'
> end
>
> it "shoule have a method of post" do
> form[:method].should == 'post'
> end
>
> it "should have a label" do
> label
> end
>
> describe "the label" do
> it "should have text of 'swinfo'" do
> label.text.should == 'swinfo'
> end
>
> it "should be for 'item'" do
> label[:for].should == 'item'
> end
> end
>
> it 'should have a text field' do
> text_box
> end
>
> describe "the text field" do
> it "should have a name of 'item'" do
> text_box[:name].should == 'item'
> end
> end
> end
>
> # second method
> it "the 'which filesets' form" do
> render
> within 'form#which_filesets_form' do |form|
> form[:action].should == '/which_filesets'
> form.should have_selector('input[type="submit"]')
>
> form.find('label').tap do |label|
> label.text.should == 'which fileset'
> label[:for].should == 'path'
> end
>
> form.find('input[type="text"]').tap do |text_box|
> text_box[:name].should == 'path'
> end
> end
> end
> end
--
You received this message because you are subscribed to the Google Groups
"rspec" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit https://groups.google.com/groups/opt_out.