Organizing Integration Test Helpers with Dominos
The domino gem by Nick Gauthier provides a great way to organize your integration test support methods. Before, I used to package test helpers as mixins.
# spec/features/admin/user_locking_spec.rb
feature 'user locking' do
include UsersTestHelper
scenario 'locking a user account' do
user = create(:user)
visit user_path(user)
lock_user_button.click
expect(page).to have_locked_notice
end
end
# spec/support/integration/users_test_helper.rb
module UsersTestHelper
extend RSpec::Matchers::DSL
def lock_user_button
page.find('section.user [data-rel=lock]')
end
matcher :have_locked_notice do |*args|
# check if there is an element matching .lock_notice
end
end
While those usally made for quite readable tests, there were two major downsides:
Findability — It quickly became hard to tell where a certain helper method was defined as soon as more than one or two mixins were used in a test.
Naming clashes — Extracting private methods to clean up test helper methods came with the risk of introducing name collisions.
With dominos you can take a more object oriented approach:
# spec/support/dominos/user_page.rb
module Dom
UserSection < Domino
selector 'section.user'
def lock_button
node.find('[data-rel=lock]')
end
def has_locked_notice?
node.has_selector?('.lock_notice')
end
end
end
The test from above now becomes:
# spec/features/admin/user_locking_spec.rb
feature 'user locking' do
scenario 'locking a user account' do
user = create(:user)
visit user_path(user)
Dom::UserSection.first.lock_button.click
expect(Dom::UserSection.first).to have_locked_notice
end
end
While this arguably reads a bit more cryptic at first, there are a couple of wins:
- It is now directly obvious where each methods is defined.
- Private methods can freely be extracted inside dominos.
- Custom matchers can be replaced by RSpec's built in predicate matchers.
- It is easy to adapt a component based mental model of your UI.
While there are other great features, the domino codebase only clocks in at about 160 LOC including doc comments. So its a rather lightweight dependency to add to your testing stack.