BDD Code analysis with Cucumber and Cuke_Sniffer

BDD Code

Behavior Driven Development a.k.a BDD is a recent and modern software development agile framework. While writing software using BDD, we use different tools but code is structured in similar way. It consist of following

  • Feature Files

Feature files are the set of features/stories and scenarios in it. Feature files are generally written in the business readable Domain Specific Language [DSL] called “Gherkin“. Gherkin use ‘Given When Then’ a.k.a GWT format for the scenarios. The feature file has .feature extension. Gherkin can be understood by most of the BDD tools. The feature file may look like this

Feature: Sports
  In order to know about different sports
  As a sport fan
  I want list of some sports

Scenario: List of the sports
  Given the system knows about the following sports::
    | name     | player           |
    | Cricket  | Sachin Tendulkar |
    | Tennis   | Andy Murray      |
    | FootBall | David Beckham    |
  When the client requests GET /sports
  Then response should be "200"
  And the JSON response should be an array with 3 "name" elements
  And response should be JSON:
   """
  [
  {"name": "Cricket", "player": "Sachin Tendulkar"},
  {"name": "Tennis", "player": "Andy Murray"},
  {"name": "FootBall", "player": "David Beckham"}
  ]
  """
  • Step Definitions

The step definitions is the code which glue the gap between business logic and technical aspect. This code makes Gherkin feature work. The step definitions can be written in the different language. The example for the step definition file with Cucumber and Ruby for the above feature file.

When /^the client requests GET (.*)$/ do |path|
	get(path)
end

Then /^response should be JSON:$/ do |json|
	JSON.parse(last_response.body).should == JSON.parse(json)
end

Then /^response should be "([^"]*)"$/ do |status|
    last_response.status.should == status.to_i
end

Then /^the JSON response should be an array with (\d+) "([^"]*)" elements$/ do |num, name|
page = JSON.parse(last_response.body)
  page.map { |d| d[name] }.length.should == num.to_i
end
  • Support Code

The support code consist of configuration of the environment and driver  (selenium, phantomjs etc ) for the web acceptance framework. The example of the support code file for the cucumber (env.rb)

require File.join(File.dirname('__FILE__'), 'sports_app')
require 'rack/test'
require "Capybara"
require "Capybara/cucumber"
require "rspec"
require 'capybara/poltergeist'

Capybara.default_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
    options = {
        :js_errors => false,
        :timeout => 120,
        :debug => false,
        :phantomjs_options => ['--load-images=no', '--disk-cache=false'],
        :inspector => true,
    }

    Capybara::Poltergeist::Driver.new(app, options)
end

module AppHelper
	def app
		SportsApp
	end
end

World(Rack::Test::Methods, AppHelper)
  • Hooks

Hook is the piece of code that can be run before or after each scenario, feature, suite or step. There are different types of hook. [hook.rb]

Before do 
	SportsApp.data = []
end

After do 
	puts "Go To Bed"
end
  • Config

The config file can be used to set profile with which we can run our features. This file can also used to generate reports. [cucumber.yml

default: --profile html_report --profile rack
html_report: --format progress --format html --out=report/features_report.html
rack: --tags @rack
  • Dependencies

There are different dependency management system for different programming languages. e.g Composer for PHP, bundler for Ruby.

We have example ‘Gemfile’ where we declare all our dependencies.

source 'http://rubygems.org'

gem 'sinatra', '1.3.1'
gem 'json', '1.6.3'
gem 'cuke_sniffer'
gem "poltergeist"

group :test do 
	gem 'cucumber', '1.1.3'
	gem 'rspec', '2.7.0'
	gem 'rack-test', '0.6.1'
end

Report

This may be optional but you can create a directory for storing html reports and other reports like cuke_sniffer reports. On CI boxes, you can create and delete these directories temporarily.

BDD code structure for me looks like this in my Sublime Text

BDD_code

 

 BDD Code Analysis with Cuke Sniffer

  Cuke_sniffer is the ruby gem and can be used for the code analysis for any cucumber project.

Installation

In order to use Cuke_Sniffer’ you need to have ruby version above 1.9.3.

$ gem install cuke_sniffer

Or Simply add this to your projects ‘Gemfile’

  gem 'cuke_sniffer'

Now update the bundle

$ bundle install

You are done  and ready to use cuke_sniffer.

Usage

Now navigate to your project where features directory is located and run

$ cuke_sniffer

When I run it with demo project, I got

cuke_sniffer

We can generate Cuke_sniffer html reports like this

$  cuke_sniffer --out html report/cuke_sniffer.html

This will generate html report and for the code analysis.

cuke_sniffer_html

Benefits of Cuke_sniffer

  • Cuke_sniffer analyses all feature file, step definitions and hooks for improvements
  • Cuke_sniffer tells us about any dead steps
  • Cuke_sniffer detect smells in the feature files and step definitions
  • Cuke_sniffer detect how many times hooks are used

GitHub

Source code of this demo is available on the GitHub

Cuke_sniffer_demo

HTML Report can be found here.

Conclusion

Cuke_sniffer can be used in the any Cucumber project for better BDD code and improve code continuously.