In this post I'm going to attempt to document some useful guidelines that in my experience has lead to writing cleaner, more maintainable and less flaky features.
Lets say we are requesting some data from a rest service and we are expecting an xml response. It may be useful for documentation purposes to show this xml response right in the feature file.
Scenario: Data Request Given I request some data from http://sample.org/data.xml I should see the xml ''' <xml> <data> hello </data> </xml> '''
Consider the following code:
Scenario: Invalid email address When I fill in "Username" with "Username" And I fill in "Password" with "password123" And I fill in "Confirm Password" with "password123" And I fill in "Email Address" with "invalid email address" And click "Create User" Then I should see "Please enter a valid email address"
There is a lot of code here that is not relevant to the scenario at all and only serves to automate the browser.
If we remove the details that aren't relevant we get a much more readable scenario:
Scenario: Invalid email address When I fill in an invalid email address And click "Create User" Then I should see "Please enter a valid email address"
Element ids, CSS and XPath is only relevant to developers and should be kept in the step definitions or removed entirely.
In the following code example we use Capybara to fill in the password text input using the label which links to it using the 'for' attribute.
<label for="password">Password</label> <input type="text" name="password"></input>
fill_in "Password", :with => "password123"
If you are using SpecFlow instead of Cucumber then Coypu is a very powerful Capybara-like .NET tool.
There should never be a situation where one scenario needs to be run before another scenario.
I've personally seen feature files that had scenarios with names that had number prefixes in order to make sure that they ran in a certain order. This is evil and should never happen.
Never ever ever let this happen:
Scenario: 0TestSetup Given some data is in the database Scenario: 1UserNavigatesToProfilePage Given the user has logged in When I click Profile Then I should see the Profile page Scenario: 2UserChangesTheirPassword When I enter a new password And I click Save Then I should see "Password changed"
Remember that whatever is more readable is always better. In the first code sample we only have one scenario so we don't need to DRY up the feature yet, but in the second sample it makes sense to add a Background section.
Scenario: Logged in user visits the user registration page Given I am logged in And I visit the user registration page Then I should be redirected to the home page
Background: Given I am logged in Scenario: Logged in user visits the user registration page And I visit the user registration page Then I should be redirected to the home page Scenario: Logged in user visits the logout page And I visit the logout page Then I should be redirected to the home page
Feature names should describe actual features. An example of a bad feature name is "A user registers an account". This feature should probably be called "Registration" or "User Registration".
Instead of multiple Thens use one Then and follow it up with Ands. The second scenario below is a lot more readable.
Scenario: Registration When I fill in user details And click Register Then I should be redirected to the home page Then I should see "account created"
Scenario: Registration When I fill in user details And click Register Then I should be redirected to the home page And I should see "account created"
Relish is a very useful new site that takes all your feature files and displays them in a very readable format.
Why not push all your features up there so that anyone in your team can have access to your feature documentation?