I’m really happy to see a resurgence in an understanding that writing integration tests that use classes and DOM structure to perform assertions within these tests is typically a bad idea. The DOM structure constantly changes but the data displayed (the stuff we want to assert is present on a page) typically doesn’t.
Why write tests against some markup that a designer may change, sometimes often if he’s iterating over a design? It’ll end up causing everyone headaches and frustration.
How can we mark up our documents without performing assertions against a deep nesting of classes and elements while ensuring our data is displayed properly?
Data attributes.
The browsers I care about support HTML5, so why not start using some of its capabilities to clean up some integration tests?
Imagine this scenario:
Scenario: See the site description on the homepage
When I am on the homepage
Then I should see the site description
Simple, straightforward, and each step is a similar level of abstraction.
Now imagine this markup:
<section class="primary-content">
<header>
<h1>Welcome to the site!</h1>
<h2>Insert a witty tagline here</h2>
</header>
<p class="description">This product will make your life 100 times
better.</p>
</section>
I could write a step like this:
Then "I should see the site description" do
page.should have_selector("section.primary-content p.description",
text: "This product will make your life 100 times better.")
end
This step is asserting that there’s a section element with a class of primary-content who has a child paragraph tag with a class of description that contains the correct text. Classes change. Structure changes. This is begging to be rewritten.
<section data-role="primary-content">
<header>
<h1>Welcome to the site!</h1>
<h2>Insert a witty tagline here</h2>
</header>
<p data-role="description">This product will make your life 100 times better.</p>
</section>
Then "I should see the site description" do
page.should have_selector("[data-role='primary-content'] [data-role='description']",
text: "This product will make your life 100 times better.")
end
Now, the step is asserting that there’s an element with a role of description within an element with a role of primary-content that contains the correct text.
XHTML introduced a role attribute, but it’s not present currently in HTML5.
Luckily, data attributes are even more flexible and we can use any conventions
we like. data-role
and data-state
are two of my favorites.
Interested in how to write awesome Cucumber steps? Head to my Test-Driven Rails workshop on March 26th and March 27th where we’ll cover this and other awesome topics on writing great tests!