Capybara "field finding" best practices

668 views
Skip to first unread message

Kyle Daigle

unread,
Jul 20, 2012, 6:57:27 AM7/20/12
to boston-r...@googlegroups.com
Hey all -

I'm curious to hear if when using Capybara, or a similar framework, you tend to use label names, element ids, CSS selectors, or what to find form fields to enter information into. I've worked on a bunch of projects that have used every variation under the sun.

It seems like label names reads the best but is easily broken if a designer changes the label text. IDs are probably the most resilient but make it slightly harder to know what you're filling in (especially when doing a nested form). Am I over thinking this?

Digital Workbox
Kyle Daigle
Digitalworkbox, llc

Wyatt Greene

unread,
Jul 20, 2012, 8:12:03 AM7/20/12
to boston-r...@googlegroups.com
When I create integration tests with Capybara, I usually think of it as testing the interface between the human user and the software.  So I tend to keep things to the level of how the end user would experience the app as much as possible.  This means I like to stick to using form labels.

I think of it as the test working properly if it breaks when a designer changes the label text.  The test is basically saying, "The interface that the end user sees has changed…did you really mean to do this?"

That said, the nature of integration tests with Capybara forces you to interact with the underlying markup sometimes.

--
You received this message because you are subscribed to the Boston Ruby Group mailing list
To post to this group, send email to boston-r...@googlegroups.com
To unsubscribe from this group, send email to boston-rubygro...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/boston-rubygroup

Brian Cardarella

unread,
Jul 20, 2012, 9:12:55 AM7/20/12
to boston-r...@googlegroups.com
What Wyatt said.

I'll add that scoping with 'within' blocks is a great way to ensure you can stick to label names. A good example is if you have an index page and each item has an 'Edit' link. Clearly you cannot just tell Capybara to click_link 'Edit'. Instead the li elements should have specific IDs attached. Scope to that id and use click_link:

within 'li#user_1' do
  click_link 'Edit'
end

----------------------
Brian Cardarella
Principal at DockYard
Visit us: http://dockyard.com
Call us: (855) DOCK-YRD
Follow me on Twitter: http://twitter.com/bcardarella
Follow us on Twitter: http://twitter.com/DockYard

Dan Pickett

unread,
Jul 20, 2012, 9:16:12 AM7/20/12
to boston-r...@googlegroups.com
within is super helpful - we've been playing with mapping friendly names with the selector to handle for when and if markup changes as we've had some brittleness problems

within_section(:first_user_li) do
  click_link 'Edit'
end
=========================
Dan Pickett
Principal at LaunchWare, Inc.

Brice Stacey

unread,
Jul 20, 2012, 9:22:02 AM7/20/12
to boston-r...@googlegroups.com
This is something I've always wanted to avoid but don't know how. I use Backbone a lot and don't add a lot of extra markup because my views have a reference to the underlying model.

It seems silly to add markup just for testing. Any ideas to avoid that?

Brice
Sent from my iPhone

Brian Cardarella

unread,
Jul 20, 2012, 9:26:53 AM7/20/12
to boston-r...@googlegroups.com
I don't think adding IDs to the markup is silly.


----------------------
Brian Cardarella
Principal at DockYard
Visit us: http://dockyard.com
Call us: (855) DOCK-YRD
Follow me on Twitter: http://twitter.com/bcardarella
Follow us on Twitter: http://twitter.com/DockYard


Brian Cardarella

unread,
Jul 20, 2012, 9:28:49 AM7/20/12
to boston-r...@googlegroups.com
In fact, if you are using the rails helper 'content_tag_for' on your objects the ids are automatically inserted.


----------------------
Brian Cardarella
Principal at DockYard
Visit us: http://dockyard.com
Call us: (855) DOCK-YRD
Follow me on Twitter: http://twitter.com/bcardarella
Follow us on Twitter: http://twitter.com/DockYard


Dylan Cashman

unread,
Jul 20, 2012, 9:41:29 AM7/20/12
to boston-r...@googlegroups.com
I think it's good to use labels for form fields (or ids named after your labels) in general, because that makes your site more accessible.  Then, when you use 

fill_in 'First Name', with: "Dylan"

you're also testing whether a speech-to-text program can access your form fields.  

I also agree with what Wyatt said - you get the most value out of testing exactly how the user would interact with the site.

We also use macros so that when we have to use selectors, it's more human readable.  You can add a method to Capybara::Node::Finders called 'last_row_of_table' that uses xpath to access the last row of a table with an id of 'consumers', and then add a method to Capybara::Session that delegates a method with that same name to current_node.  Then, you can write things like this:

within(page.last_row_of_table('consumers')) do
  click_link 'Edit'
end

Dylan Cashman
Annkissam - Mission Driven Systems
www.annkissam.com

One Broadway, 14th Floor
Cambridge, MA 02142
Cell (preferred): 617-999-3634
Office: 617-401-2480, ext. 708
Fax: 617-507-5922

Jeremy Weiskotten

unread,
Jul 20, 2012, 9:47:36 AM7/20/12
to boston-r...@googlegroups.com
Pro-tip: if you're using Haml, you can use this notation to easily add an id and class to the element:

%li[user]

Given a User object with id 99, that renders the following HTML:

<li class="user" id="user_99">

It's not something you need all the time, but it comes in handy.

Rob Park

unread,
Jul 20, 2012, 11:20:17 AM7/20/12
to boston-r...@googlegroups.com
+1.

In fact, I'd recommend the test be written first and drive the name of the id.

//rob

Dan Croak

unread,
Jul 20, 2012, 12:38:39 PM7/20/12
to boston-r...@googlegroups.com
Some folks advocate for rel attributes on links to focus the tests on semantics:


Rob Park

unread,
Jul 20, 2012, 12:46:10 PM7/20/12
to boston-r...@googlegroups.com
I subscribe to that line of thinking as well.
I wasn't suggesting the id itself be in the scenario (or even the step) in its raw form.

e.g.
When I submit an "authorization"   
may have a step that uses an AuthorizationPage object which will have a "submit" method to click the submit button...

Is that what you were getting at?

//rob

Eduardo Gutierrez

unread,
Jul 20, 2012, 12:54:36 PM7/20/12
to boston-r...@googlegroups.com
I've been using 'data-' attributes in a few projects and ended up with
a set custom Capybara selectors and a module I include into
Rspec/Turnip/Cucumber to find elements to interact with or scope
actions to.

https://gist.github.com/3151818
Reply all
Reply to author
Forward
0 new messages