Rob Sullivan and Amanda Harlin have been kicking around ideas for something called Techlahoma and they recently asked me to get involved to help. We decided early on that the app would be a Rails project, and I suggested that we use Cucumber to describe the main user features that we hope to build. In the early stages these stories will act as our design document, allowing us to formally capture the description of the features that will be available to end users. These documents will live in the project repo, and will be just like any other code/text file. We'll be able to track the history of feature descriptions, make drastic changes to them without fear of losing previous work, use pull requests to initiate discussion about new features, and all of the other great benefits that you get with git and GitHub.
I had the honor of generating the new app, so here I'm going to document the steps that I took to start the project and build the first few Cucumber scenarios.
First I generated a new rails app, using postgres as the DB and using the
-T option to skip
Test::Unit. Then I immediately initialized the project directory as a git repo, added all of the app files to the repo, committed and pushed.
rails new techlahoma -d postgresql -T cd techlahoma git init . git add . git commit -m "Initial rails app" git remote add origin firstname.lastname@example.org:techlahoma/techlahoma.git git push -u origin master
Then I added a couple of gems to the
Gemfile for running cucumber.
group :test do gem 'cucumber-rails', :require => false # database_cleaner is not required, but highly recommended gem 'database_cleaner' end
Then a quick
Then I installed the cucumber configuration and skeleton.
rails generate cucumber:install
Now I'm ready to run cucumber!
$ cucumber Using the default profile... 0 scenarios 0 steps 0m0.000s
Cucumber is running, but I don't have any scenarios ready to run. Let's fix that. One of the features that we know we want to have is the ability for users to sign in and out. So, I'm going to start there with a feature description. First let's look at the feature files themselves, and then I'll describe their structure.
Feature: Sign In As a visiting user I want to sign in Sign in will happen via GitHub (and possibly other auth providers) Scenario: Sucessful sign in Given a signed out user When he visits the home page Then he should see "Sign In" # A link on the page When he signs in Then he should see "Sign Out" # A link on the page Scenario: Failed sign in Given a signed out user When he visits the home page Then he should see "Sign In" When he fails the signs in Then he should see "Sign In" Then he should see "sorry"
Feature: Sign Out As a signed in user I want to sign out To protect my account stuff Scenario: Successful sign out Given a signed in user When he visits the home page Then he should see "Sign Out" When he signs out Then he should see "Sign In" Scenario: Failed sign out Given a signed in user When he visits the home page Then he should see "Sign Out" When he fails the sign out Then he should see "Sign Out" Then he should see "sorry"
As you can see, these feature files have two main parts.
Feature section is only for humans, and is meant to be a high level description of the complete feature or feature set in question. In this part you're not describing specific use cases or sequences of events, you're just describing the purpose of the feature, and the "business case" for why it exists in the first place.
Scenario sections are also for humans, but they're for computers too. These are descriptions of specific sequences of events that should happen within the app, and the results that should occur with those events. Generally you'll have a
Scenario section for each branch, or edge case that your code will need to cover. You want to keep these descriptions still at a pretty high level, and you don't want to get into the minutia of dealing directly with UI elements. Notice that the scenarios above have only a single line for something like
When he signs in.
Scenario sections generally should not contain things like "she clicks on the 'sign in' link" or "she enters her email address". These kind of details will be handled later in the step definitions, which is the code that Cucumber will actually run in order to execute these
Scenarios as live test code.
Now when I run cucumber I see that it's trying to execute my
Scenarios but that it can't find step definitions for them. Handily it provides stubs for the missing step definitions.
4 scenarios (4 undefined) 22 steps (22 undefined) 0m0.212s You can implement step definitions for undefined steps with these snippets: Given(/^a signed out users$/) do pending # express the regexp above with the code you wish you had end When(/^he visits the home page$/) do pending # express the regexp above with the code you wish you had end Then(/^he should see "(.*?)"$/) do |arg1| pending # express the regexp above with the code you wish you had end When(/^he signs in$/) do pending # express the regexp above with the code you wish you had end When(/^he fails the signs in$/) do pending # express the regexp above with the code you wish you had end Given(/^a signed in user$/) do pending # express the regexp above with the code you wish you had end When(/^he signs out$/) do pending # express the regexp above with the code you wish you had end When(/^he fails the sign out$/) do pending # express the regexp above with the code you wish you had end
The great thing about cucumber files is that you can start will just the
Feature section and allow it to act like a design document of sorts where you capture general ideas about the new feature that's being discussed. I know that one of the things we'd like to include is the ability for companies to maintain a profile that contains some basic information about the company. I'm not entirely sure what all we want to include there, so for now I'm going to start with a some basic feature files that just take a stab at describing things that might fit into this feature set.
Feature: Company Profiles As a company owner/operator I want to create a profile for my company So that local developers can learn about me
Feature: Tags for Companies As a local developer I want to be able to filter companies based on technologies being used So that I can find places where my skills can be put to use
Feature: Freelancer Profiles As a local freelancer I want to create a profile for myself So that local companies can contact me if they could use my skills
These files aren't yet executable by Cucumber, but they're a great starting point for discussion about what we want to have happen here. We can use them to flush out the ideas and zero in on the requirements. As that happens usage scenarios will begin to emerge and we'll write a
Scenario section for each use case that we want to consider.
In a later installment we'll look at starting to implement some step definitions for scenarios to turn these feature files into fully executable tests.
In the mean time you can "check out the techlahoma repo":https://github.com/techlahoma/techlahoma and don't hesitate to send over some pull requests if you'd like to get involved.