CSC/ECE 517 Fall 2012/ch1b 1w71 gs
Cucumber and Capybara
Introduction
Cucumber is one of the latest additions to the RSpec family of tools for testing in Ruby. Testing is one of the most important parts of the Ruby culture. It allows programmers and software development teams to describe feature based tests in plain text definitions known as "stories". This text is written in a business readable domain-specific language(DSL), most widely used is Gherkin, although you can use testing environment specific languages also like the Capbara DSL
Though Cucumber is a testing tool, the main intent of its development is to support Behavior Driven Development(BDD) which is derived from Test Driven Development. This implies that the tests written in DSL are typically written before any other part of the code is written. It is analysed by the non technical stakeholders and then the production code is written. The production code is thus written outside-in, in such a way that the tests pass.
Cucumber provides support for a wide range of Ruby virtual machines such as JRuby, alternative application frameworks such as Sinatra, other programming languages such as Python, test environments such as Capybara and provides i18n language support for feature and step files.
This article primarily focuses on running Cucumber tests on the Capybara testing environment. It carries all the information about the driver running the test and comes with a built in support for Rack::Test and Selenium.
Capybara is a testing environment that simulates the manner in which a real world user would interact with the application. It requires no explicit setup for Rails applications. The most powerful feature of Capybara is that it has a very intuitive application program interface that understands any language an actual user would use. With the libraries and drivers provided by Capybara for deploying web applications and for interacting with service applications, the testing requires minimum amount of coding.
History and the need for development
Cucumber is actually Aslak Hellesoy's revamp of RSpec's "Story Runner"(by Dan North). The earlier versions of "Story Runner" and its predecessor RBehave required that the stories be written in Ruby. But seeing the associated inconvenience, David Chelimsky added the plain text support with contributions done from an eclectic support team.
In April 2008, Aslak Hellesoy started the Cucumber project to iron out the inherent flaws and glitches of the RSpec Story Runner. Joseph Wilk and Ben Mabey were the regular contributors to the project. Matt Wynne joined in September 2009. In October 2009, Mike Sassak and Gregory Hnatiuk did some great work on a faster parser for Cucumber. In addition to the core team, there were over 250 developers contributing to the overall development of the project.
Though Cucumber is written in Ruby, it can be used to test code written in Ruby and other languages too. Not limited to Java, C# and Python. It required minimal use of Ruby and is hence believed to be extremely easy to code. Moreover, the user stories for the features can be written in any human language.
Ever since, Cucumber has seen a lot of revision and refactoring. One of the major refactoring include transferring certain implementation portions to make it customized for particular frameworks
Setting up Cucumber
Generic installation
Install Ruby on the system
gem install cucumber
To read up on more information about this gem
cucumber --help
On Ruby on Rails 3.x
Cucumber-Rails is used for performing Cucumber tests on Rails.
Step 1 : Add the following to the Gem File
group :test do gem 'cucumber-rails', :require => false # database_cleaner is not required, but highly recommended gem 'database_cleaner' end
Step 2 : Then install the gem
bundle install
Step 3 : Bootstrap your Rails app by
rails generate cucumber:install
How Cucumber works
Cucumber testing comprises of two components namely
- Feature
- Step Definitions
Features
Features are essentially outward facing in the sense that they describe the ideal outcome given a state of the system. A given state of the system is the cumulative input to the system comprising of the events taking place in the given context and the predefined variables. Each feature is a collection of scenarios. The scenarios each are described by the given/when/then + and/but construct. Features are also known as matcher methods and are integral link to the step definitions. Now when Cucumber is executed the corresponding block of Ruby code is invoked. Scenarios are independent of each other and once a scenario execution is over there is nothing which is carried over to the next scenario.
Given/When/Then + And/But construct
Given : Purpose of given is to create a setting for user interaction with the system. These are analogous to the pre-conditions of Usecase.
When: This for the main actions the user performs ‘given’ a scenario i.e. transition of state which has an observable effect.
Then: This is majorly to check the consequences of the action performed by the user i.e. what is the output of the system when a particular input is given.
And/But: These are used when there are multiple given conditions for which some actions need to be performed.
An Example:
Scenario: Manifold Givens Given the username And Given the password When I press enter Then I see the username on the screen But I do not see the password on the screen
Step Definitions
Step definitions are primarily inward facing as they map the outward facing scenario statements with the inner Ruby code snippets. Step definitions either consists of keyword, string or regular expression. The mapping is mostly done by expression matching and calling the appropriate code snippets in the Ruby code.
Setting up Capybara
As explained before, Capybara doesn't require explict set up for Rails applications. For Rails, we add the following line to the test helper file:
require 'capybara/rails'
Example of running Cucumber tests on Capybara
After setting up cucumber-rails and Capybara as described above, the following example describes how an actual cucumber test is written and run in the Capybara environment. It is also possible to use the Capybara DSL for writing the tests but the most widely used DSL is Gherkin. The example below uses Gherkin but it can be easily transformed using the DSL provided by Capybara.
Features and Scenarios: As discussed above, the features ... In the example below, the feature describes a scenario within a banking system where a student needs to test the system's ability to find the simple interest on a given principal at a given rate per year.
# Language: English Feature: InterestCalc In order to avoid an error in interest calculation As a new student I want to be told the interest for given principal per year Scenario: Interest on Principal * I have entered 1000 into the interest_calc * I have entered 3.5 into the interest_calc * I press calc * The result should 35 on the screen
Step Definitions: As discussed before, the step definitions provided the mapping for the corresponding code snippets that each scenario within the feature interacts with. In this example, for the givens, we first create an object of the class Interest_calc and push the arguments into the instance. Then for when, we call the corresponding method that calculates the interest. For the then, we display the result on the screen.
require 'capybara/cucumber' require 'Interest_calc' Given /I have entered (.*) into the interest_calc/ do |n| @calci=Interest_calc.new @calci.setdata(n) end When /I press (\w+)/ do |op| @result=@calci.calc end Then /the result should be (.*) on the screen/ do |result| @result.should == result.to_f end
Class definition: This is the Interest_calc class that is accessed in the step definition.
class Interest_calc def push(n) @args ||= [] @args<<n end def calc @args.inject(0){|p,r| p=p*r/100} end end
Advantages
The advantages of Cucumber are that it mandates a person to spend more time in the planning phase before directly getting into the complexities of models, views and controllers. It lets one have a broader perspective of the application one intends to develop. The syntax which is in simple English is what makes it unique letting clients who are not aware of the technicalities of a system, voice their opinion in the development process and hence the development is always in sync with the requirement.
Ongoing developments
Cucumber has rapidly become one of the most preferred tools for automated testing. Aslak Hellesoy and his team are working on further advancements and improvements to the tool. Improving the documentation via the "The Cucumber Book" being one of them. The book continues to be revised to keep up with its rapid evolution. Currently, Cucumber tests run on JVMs through JRuby. But to overcome the inherent latency, the team is working on a native Java implementation of the tool which can be built in to the Java development environment. During this adaptation to Java, the team also found aspects of the Ruby implementation that could be improved to make it much more flexible.
References
- http://cukes.info/
- http://www.rubyinside.com/cucumber-the-latest-in-ruby-testing-1342.html
- http://www.allenwei.cn/cucumber-capybara-what-we-need-for-rails-integration-test/
- http://railscasts.com/episodes/155-beginning-with-cucumber
- http://rubysource.com/smelly-cucumbers/