Skip to content

Instantly share code, notes, and snippets.

@manlycode
Created March 17, 2014 13:20
Show Gist options
  • Save manlycode/9599052 to your computer and use it in GitHub Desktop.
Save manlycode/9599052 to your computer and use it in GitHub Desktop.

Rails Testing Anti-patterns: Domino

I enjoy integration testing Rails applications. Not only because it’s an
essential practice, but because I’m too lazy to have to click through an
application on my browser if I don’t have to. I enjoy clean integration tests
even more. My job is very easy when I can jump onto a new project and clearly
understand what an integration test is trying to prove.

Recently, I was shown a tool to improve the clarity of tests. The
Domino Rubygem. Domino lets you seperate
DOM selectors from your Capybara integration tests, and makes DOM assertions
look like a clean DSL than selector string scattered throughout your tests.

Being a fan of DLS and abstraction, I went bananas writing DSLs with Domino. But
quickly found out that made more work for myself. The following catalogs a few
of these pitfalls, and offer simpler alternatives.

Starting With Good Intentions

Starting out writing Domino classes, I understood the basics: a dom
element has a selector, and an instance of the class has a node helper method
which returns a Capybara::Node object. So here’s an example of the code I was
writing:

In this example, I’m trying to assert the state of a shopping cart link. The
cart will have an item count.

My thinking in writing this Domino class went something like this

Since I’m dealing with numbers, building the assertion so that I can use a
Ruby integer would be nice. That’s what I’d do if I were asserting the count on
and ActiveRecord model, so I’ll make it look similar.

While this works, and provides a clean interface for RSpec assertions, I
eventually ran into some pitfalls.

Hitting a Brick wall

The DSL was great! The assertions green on full page loads, and I had a simple
way to communicate with clarity, what the test is checking.

But things were red once I introduced AJAX. Adding a cart item should increase
the count by 1:

Come on!

The JavaScript was correct. The mechanics of the client-side code worked when I
would hand test it. What was going on?

Chucking breakpoints into the code revealed that the test was green when waiting
before the assertion. It was a timing issue, the bane of exercising any
JavaScript heavy code.

Simplification with Domino Attributes

A shallow dive into Capybara’s documentation reminded me of how to wait for DOM
updates. You don’t. It automatically happens as long as you use Capybara
matchers (e.g. have_content, have_css). So I refactored:

This example leverages a Domino
attribute. This specifies a helper method on the
class which returns a DOM element within the selector, having the “.count”
class.

This impacts the overall assertion used in the test. It doesn’t use an integer
to compare anymore, instead a string. The trade-off is a few extra characters in
the test, but the have_content matcher is less brittle than eql matcher.
Additionally, it waits for the DOM to update. So we trade off a few characters
for better, green tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment