We use "Futurelearn style" acceptance tests This blog post has been removed from the internet.
- Use a single scenario per file. This prevents the files from becoming too large. Separate logical blocks of steps with newlines.
- Use instance variable to carry state between steps. Do not use
let
orbefore
blocks. - Define all steps in the file. If you want to share code between scenarios, call helpers that are defined in a module from the step.
- The steps should be written in English. Do not use parameters to call the step methods.
A good test looks like this:
# do_a_thing_feature_spec.rb
RSpec.describe 'Do a thing feature' do
include TestHelpers
scenario 'User does a thing' do
given_i_am_signed_in
when_i_press_a_button
then_something_should_happen
end
def given_i_am_signed_in
@user = create(:user)
sign_in(@user)
end
def when_i_press_a_button
click_link_or_button 'Do the thing'
end
def then_something_should_happen
expect(@user).to have(done_something)
end
end
# helpers.rb
module TestHelpers
def sign_in(user)
# do the thing
end
end
A less good test looks like this:
# do_a_thing_feature_spec.rb
RSpec.describe 'Do a thing feature' do
include TestHelpers
let(:user) { create(:user) } # Bad: a `let` block adds noise to the file and adds indirection
# Bad: a `before` block adds noise to the file and can make it unclear why something is set up
before do
sign_in_user(user)
end
scenario 'User does a thing' do
when_i_press_a_button('Do the thing') # Bad: a parameterised method makes the step harder to read
then_something_should_happen # Bad: hidden in a module
end
# Bad: multiple scenarios clutter the file and slow down the test suite
scenario 'User does a different thing' do
when_i_press_a_button('Do the thing') # Bad: a parameterised method makes the step harder to read
then_something_else_should_happen # Bad: hidden in a module
end
# Bad: a parameterised method
def when_i_press_a_button(text)
click_link_or_button(text)
end
def then_something_else_should_happen
expect(@user).to have(done_something_else)
end
end
# helpers.rb
module TestHelpers
def then_something_should_happen
expect(@user).to have(done_something)
end
end