Behaviour Driven Development with Sinatra + Cucumber, Capybara, and Rspec expectations

Hello all,

On this blog post we’re going to write a very simple flight api to see destinations.
My intention here is to guide, walk you through, on how to test, drive your code, using cucumber and others.

First of all, dependencies.

Make sure you have the following gem on your Gemfile.

source :rubygems
ruby "2.0.0"

gem "sinatra"
gem "sinatra-assetpack", "~> 0.3.2", require: "sinatra/assetpack"

group :test do
  gem "cucumber"
  gem "capybara"
  gem "capybara-webkit"
  gem "rspec-expectations"
end

Asumming you have relady run: bundle

Create a file in features/home_page.feature and open it up in your editor/ide of choice, I use vim.
Here we go now, we’re going to write out first cucumber feature. However what’s the definition of a feature or a scenario?

A cucumber feature is:

In cucumber, a feature is a high-level requirement expressed from the perspective of a person or another computer using
the system. Features play a role similar to that of user stories in XP.
source: The RSpec book

Or you can read this Feature Introduction

Great, I assume that you must know what cucumber features are by now.

Let’s write our first Acceptance test.
Before, make sure you have created a file under the dir features/support/env.rb

Feature: Displaying departures
  Given Paul is on our website
  And he wants to see a list of departures

Background:
  Given a Paul is on home page
  Scenario: List of departures
  Then he should see a list of departures

And now, we run it:

cucumber

You should an output like this:
cucumber_feature
What that means is cucumber telling us what we have to do next, this is the beauty of writing tests.
Once you’ve written it, if you follow the laws of TDD/BDD you will always now what the next step is and most important
when you are done with a feature/functionality.

Right, so now we have to implement those pending steps.
Create and open up a file under the dir feature/step_definitions/home_page.rb

I tend to copy and paste that output cucumber gives us, and then write our tests.
I also like writing a small DSL to enforce what we are testing rather than writing those methods that a testing framework provide.

Given(/^a Paul is on home page$/) do
  customer_is_on(:home_page)
end

Then(/^Paul should see a list of departures$/) do
  user_should_see_a( list: ".departures li", count: 3, text: /./ )
end

Let’s define a helper under the dir features/support/helpers.rb

module Helpers
  def customer_is_on(path)
    visit( path == :home_page ? "/" : path )
  end
  alias :are_on :customer_is_on

  def should_see_a(*args)
    attributes = args.first
    tag = attributes.delete(attributes.first[0])
    page.should have_css(tag, attributes)
  end

  def user_types_in(element, text)
    fill_in element, with: text
  end

end

World(Helpers)

What we just did was, we create a Ruby module, some methods and included it into  cucumber World using World method.
Whenever we write code like this it becomes easier to change, embrace change, and we do not have to hard-code a lot of stuff.
For example if we were to write it like so:

Then(/^Paul should see a list of departures$/) do
  %w{ New\ York Japan Paris }.each do |city|
     page.should have_content(city)
   end
end

What happens if we’d like to change those city names? we would have to come back to this test and hard-code it again.
What if we could write tests that still tests the behaviour but we do not have to hard-code a lot?

Awww_yeah

Yes we can :), With the help of capybara and our good Ruby skills plus our brains we can do so.
Let’s examine this snippet of code:

def should_see_a(*args)
  attributes = args.first
  tag = attributes.delete(attributes.first[0])
  page.should have_css(tag, attributes)
end

The good thing of doing this is that it enforces our tests to be more readable, we can reuse this method later on, and we can integrate this in
almost any context.

Okaay, let’s get this done.
What we do now? we run our tests again.

cucumber

What happens now? It fails, yeah this is the first step of TDD.
Now that we’re RED, we need to write just enough code to make our tests go GREEN and the RE FACTOR.

Create and open up file under root dir named app.rb

require 'sinatra'
require 'sinatra/assetpack'
require 'json'
class MyApp < Sinatra::Base
  register Sinatra::AssetPack
  assets do
    js :application, [ "/js/jquery-1.11.0.min.js", "/js/index.js" ]
  end

  get '/' do
    @departures = [1,2,3]
    erb :index
   end
end

Note that I have written some code to require our assets, css and js files, relying on the gem sinatra-assetpack.
What do we do next? We run our test suite again.

cucumber

And now it, capybara, complains that it can not find those elements we have told it to find.
So the next step is to write our view under the dir views/view.erb
Which you can check out here.

Great, we run our test suite again.

cucumber

, and
Fuck-Yeah-meme

We have our first test, user story, passing.
How awesome is that?

I think this is enough, there is a lot more I’d like to go through but time is limited.
If you like this little sinatra app, you can check this out here on Github, I have written another acceptance test, user story, that
tests when a user types in a name of a city to see that city’s destinations.
It uses Ajax to send this data to the server and updates the page showing destinations found or an error message.

Please do not hesitate to criticise or teach me if I have forgotten something or if you think you have a better way of doing this.

 

Polymorphism and Traffic Lights

Hi,

In this blog post I going to share with you how I understood
the concept of Polymorphism. I will not use complicated
technical language, as I want to make it fairly simple to understand.

First, what does the word polymorphism mean?
Poly -> More than one, multiple, many. ( e.g a polygon is many-sided )

20-sided_dice-thumb-430x433-119154

Morph -> Change or form. ( Morpheus the Greek God of dreams able to take any form ).

morpheus-chair

Nope, not this one but this:
morpheus-iris-01

Cool, with the help of this images your brain will assimilate this much faster and you probably will
never forget what these two words mean.

Imagine you’re going back home after a lovely day at work and
that you are an instance of object Person.
traffic_lights

As you can see on the image above, there are different objects (i.e people )
which are responding to the messages being sent from the TrafficLight object.
It does not matter if the objects have a green colour neither if they’re naked or not feeling well.What really matters is that each object responds to the message that TrafficLight object is sending out.

How do they respond to these messages ?
By agreeing on a protocol which in this case is:
See Message Passing

  • Do not move when message is “Red“.
  • Move forwards when message is “Green“.
  • Stop when message is “Orange“.

I do have to say that bugs can occur and some objects will behave differently, if they have
been overridden at some stage during the program execution ( i.e drunk driving ).
Some of them may be a work in progress object that they will probably stall out their vehicle.

Rationale:

Traffic light object sends a message to its known objects ( i.e people waiting by )
These objects know that if traffic light object sends a message saying
Red” they should respond to it by waiting until traffic light object sends them a message
saying “Green“.
How are they going to wait? That does not concern TrafficLight object, some of them might wait by looking around, or thinking about their lives. Once the “Green
message is received from TrafficLight object they know that they’re allowed to move.

I hope you understood what Polymorphism is in Computer Science in a less complicated
explanation.

ABC = Always Be Coding