Access your teaching qualifications - Testing styleguide
Feature / System tests
We use "Futurelearn style" feature tests.
Our feature tests live in spec/system
.
Rules
- 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.
Examples
A good test looks like this:
# do_a_thing_feature_spec.rb
RSpec.feature "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_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.feature "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 { sign_in_user(user) }
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_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
Component / Unit tests
This project is less prescriptive about lower level testing, but we try and conform to some of the ideas outlined in these posts: