Guillem Fernandez

About my job and my passion.

BDD - From the Idea to the App

This article is about how to move from this:

“In order to avoid mistakes users must be able to calculate a sum. As example, starting on the Welcome Screen when I touch “3” and I touch “+” and I touch “2” and I touch “=” then I should see a “5” in the screen. When I touch “4” and I touch “+” and I touch “2” and I touch “=” then I should see a “6” in the screen.”

To this:

Simple Calculator Screen

Using BDD it provides you a simple, easy and fast mechanism to keep the communication between technical and non technical integrators of the project, you are going to understand how reading this article. The audience of this article is basically technical people that is constantly in contact with Product Owners or Stackehodlers that claims for functionalities, or in scrum terms product histories that they have clear in their minds but aren’t able to transmit in the a way that a technical person understand.

Let’s go to a simple but clear example. An accountant wants to add a function to his calculator that enables him to put positive numbers un green, and negative numbers in red. Looks pretty simple, doesn’t it? … No! … we have a conflict here, because there is a case left to interpretation, what happens with zero?

The answer comes from a little more elaborated requirement like:

“If the number in the display is greater than zero then it’s colour should be green. If the number in the display is less that zero then it’s colour should be red”

And then you can see a gap in this requirements so you can fix it adding:

“If the number in the display is greater than zero then it’s colour should be green. If the number in the display is less or equal than zero then it’s colour should be red”

And this is a sentence that both can understand and doesn’t leave space for interpretations. And better than this, is usable to develop an App.

Step 1: Let’s put things in context

To read more about BDD you have great resources like Cucumber - Making BDD fun or books like The Cucumber Book, but I’m not going to explain what is BDD because it is outside the scope of this article. Instead of it, I’m going to focus BDD in a very practical way and centred in iOS.

As a summary, we could say that Cucumber is a set of rules and procedures that, using a syntax called Gherkin, allows you to use requirements written in a ‘natural way’ to set acceptance tests. To do it, it uses a script that takes your Features and using a set of step definitions that you have to create, runs the tests on you App. It is probably best explained with an example.

  1. Run cucumber in your command line.
  2. Cucumber looks for your firs Feature
  3. The Features says “I press ‘2’ “ in his first step
  4. Cucumber doesn’t know how to “Press ‘2’”
  5. Cucumber looks for step definition.
  6. The step definition says “Touch a number means to look for a button with that number on his label and start touch action”
  7. Cucumber performs the action.

Of course the step definition is not created in natural language, but in Ruby. Don’t be scared about it, it’s very easy to learn the few Ruby rules you’ll need to define the steps.

If you find something missing here you are right. There is a peace in this puzzle missing. How does cucumber communicate with iOS apps, Ruby applications, .Net applications or any other kind of application? is it universal? The answer is no, there are different Cucumber implementations for different OS and different programming languages. In this case I will use Calabash. The reasons why I decided to use Calabash are basically because the have great documentation, it’s got support for gestures and it’s implemented for iOS and Android so you can use the same features to run Android and iOS tests.

Step 2: Let’s set it up

To start using cucumber you have to have the script installed. To do it first of all, test your Ruby installation by opening your terminal and running ruby -v. You should see something like this.

Terminal running ruby -v command

If you haven’t installed a newer version of ruby, in mountain lion you should see “ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0].” instead of “ruby 1.9.3p194 …”. Calabash works with version 1.8.7, but if you are going to go further in BDD, I’d recommend to install rvm and then instal a version 1.9.x so you can use all the new features of Ruby 1.9.

Next is installing calabash. To do it simply run “sudo gem install calabash-cucumber” to install calabash. And that’s it … you’ve got it.

!!!IT IS VERY IMPORTANT THAT YOU HAVE Xcode Command Line Tools INSTALLED!!!!

Project creation screen

Now let’s prepare out project to run tests. Go to Xcode (I’m running Xcode Version 4.5 (4G182) at this moment) and create a new Single View Application project.

Project creation screen

Once you’ve got it, close Xcode to make some changes in the project. In your terminal, go to your project folder, where you see your .xcodeproj file, and run in the terminal “calabash-ios setup” to setup your iOS project and “calabash-ios gen” to generate a skeleton features folder for your tests.

Running calabash-ios setup

Running calabash-ios gen

At this point we have our project ready to start BDDing. To test that everything went fine, just run from the command line the command “cucumber” and you should see how it tries to test the default feature.

If you have any problem setting up your project, take a look at Calabash iOS page where you’ll find a tutorial to setup your project for using calabash in deep detail.

Step 3: Let’s start with BDD

First of all we have to take a look on the new structure we have in our project, the skeleton of cucumber. Let’s take a look on it.

Folders structure created

  • calabash.framework - We are not touch this folder as here is where the framework lives.
  • features - This is the folder where we’ll play our magic.
    • my_firts.feature - This is a sample feature just to give us a clue about how to use it.
    • step_definitions - The folder where we’ll define the way the steps must be done.
    • support - Folder with support ruby files. We are not going to use it in this tutorial.
  • irb_ios4.sh - This is a script to run irb with all calabash definitions to use with iOS 4. We won’t use it in this tutorial,, but just for you to know it’s a command line utility to run Ruby scripts interactively with test purposes.
  • irb_ios5.sh - The same as the previous one but for iOS 5.

Let’s create our first feature then. Go to your favourite text editor and create a file named sums.feature and place it into your features folder. A feature is a functionality you want to test. Each feature is composed by a different number of scenarios which are in essence simple behaviours related to the feature that can be tested atomically, and each scenario is formed by a number of steps where you can perform actions and check responses. The best way to understand it is by translating our requirement text into features.

In the initial text we have to scenarios:

  1. starting on the Welcome Screen when I touch “3” and I touch “+” and I touch “2” and I touch “=” then I should see a “5” in the screen.
  2. When I touch “4” and I touch “+” and I touch “2” and I touch “=” then I should see a “6” in the screen.

Let’s create the feature by removing all the unnecessary text and reordering it:

Feature: Sums 
    In order to avoid mistakes users must be able to calculate a sum

  Scenario: Sum 3+2 = 5
    Given I am on the Welcome Screen
    When I touch "3"
    And I touch "+"
    And I touch "2"
    And I touch "="
    Then I should see a "5" in the screen

You can see here some keywords like Given, When, And and Then. Internally they are ignored, but they are great to put it in a format that can be easily read by non technical persons. I wont go into detail about how to move from text 1 to Scenario Sum 3+2 = 5 because it depends a lot on the case and has a lot of simple common sense.

Ok, we save and try to run the tests typing “cucumber features/sums.feature” in the Terminal window to run only the feature we are working on and we get the following result.

Test execution result

Let’s analyse it. The firs message to analyse is:

  Unable to auto detect APP_BUNDLE_PATH.
  Have you built your app for simulator?.
  Searched dir: /XXXXXXXXX/Library/Developer/Xcode/DerivedData/SimpleCalc-gvyjencvuqnnzcfxfncxonfqupys/Build/Products
  Please build your app from Xcode
  You should build the -cal target.

This basically means that cucumber can’t find the App to run the tests. So let’s do what he suggests, open Xcode, select the target, in this case SimpleCalc-cal → iPhone 6.0 Simulator and build with ⌘B so we generate SimpleCalc-cal.app.

Select SimpleCalc-cal target

Now running again “cucumber features/sums.feature” the result is completely different. The iPhone simulator starts and our App is executed. If it doesn’t, check you have “Enable access for assitive devices” checked in System Preferences → Accessibility.

Enable access for assitive devices

And the result should be something like this:

~/Development/Tests/Self/SimpleCalc ➜cucumber features/sums.feature 
Feature: Sums
  In order to avoid mistakes users must be able to calculate a sum

  Scenario: Sum 3+2 = 5                   # features/sums.feature:4
-------------------------------------
Auto detected APP_BUNDLE_PATH:

APP_BUNDLE_PATH=/XXXXX/Library/Developer/Xcode/DerivedData/SimpleCalc-gvyjencvuqnnzcfxfncxonfqupys/Build/Products/Debug-iphonesimulator/SimpleCalc-cal.app

Please verify!
If this is wrong please set it as APP_BUNDLE_PATH in features/support/launch.rb
-------------------------------------
Ping http://localhost:37265/...
Fetch version http://localhost:37265/version...
    Given I am on the Welcome Screen      # features/step_definitions/my_first_steps.rb:1
    When I touch "3"                      # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
      playback failed because: query view marked:'3' found no views. Is accessibility enabled?
       (RuntimeError)
      features/sums.feature:6:in `When I touch "3"'
    And I touch "+"                       # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    And I touch "2"                       # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    And I touch "="                       # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    Then I should see a "5" in the screen # features/sums.feature:12

Failing Scenarios:
cucumber features/sums.feature:4 # Scenario: Sum 3+2 = 5

1 scenario (1 failed)
8 steps (1 failed, 3 skipped, 3 undefined, 1 passed)
0m4.563s

You can implement step definitions for undefined steps with these snippets:

Then /^I should see a "(.*?)" in the screen$/ do |arg1|
  pending # express the regexp above with the code you wish you had
end

Here the colours are important as they are highlighting the first step that fails with red so there is no point in continuing with the scenario and the scenario is marked as failure. Analysing the error message:

    When I touch "3"                      # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
      playback failed because: query view marked:'3' found no views. Is accessibility enabled?
       (RuntimeError)
      features/sums.feature:6:in `When I touch "3"'

Cucumber tells us that he can’t find any “3” to touch, so we have to create those numbers. To do it, go to Xcode and in the Interface Builder make ViewController.xib look like this:

Calculator view

And then Clean (⇧⌘K) and Build (⌘B) and run again your test “cucumber features/sums.feature”.

First green in test

Look, some green in our tests and we can see the App how buttons are being pressed. But there is still a problem, Calabash is telling us that it doesn’t know how to evaluate Then I should see a “5” in the screen, and here starts part of the great value of the framework, how it suggest how to implement the steps.

You can implement step definitions for undefined steps with these snippets:

Then /^I should see a "(.*?)" in the screen$/ do |arg1|
  pending # express the regexp above with the code you wish you had
end

So let’s do it. Again with your favourite text editor, create features/step_definitions/sums_steps.rb file and paste inside it the step definition suggestion. Inside this function you need to determine what is see something in the screen, and this is where Ruby comes to scene, you can read in Calabash Wiki all the predefined steps and how to create new steps, and I’m not going to go deeper in this point on how to create those steps, I will probably do in following tutorials if there is demand on.

To get what we want its enough with checking that there is a view called screen and that the value of the text in it is the number we pass as parameter. It can be done with the function check_element_exists. It gets a parameter that is the query to execute with the values needed. I’ll go deeper in following tutorials as I commented, but the result should be this:

Then /^I should see a "(.*?)" in the screen$/ do |arg1|
  check_element_exists("view marked:'screen' text:'#{arg1}'")
end

So the function returns true if the view selected exists.

Saving and running the test you should get something like this:

~/Development/Tests/Self/SimpleCalc ➜cucumber features/sums.feature 
Feature: Sums
  In order to avoid mistakes users must be able to calculate a sum

  Scenario: Sum 3+2 = 5                   # features/sums.feature:4
-------------------------------------
Auto detected APP_BUNDLE_PATH:

APP_BUNDLE_PATH=/XXXXXX/Library/Developer/Xcode/DerivedData/SimpleCalc-gvyjencvuqnnzcfxfncxonfqupys/Build/Products/Debug-iphonesimulator/SimpleCalc-cal.app

Please verify!
If this is wrong please set it as APP_BUNDLE_PATH in features/support/launch.rb
-------------------------------------
Ping http://localhost:37265/...
Fetch version http://localhost:37265/version...
    Given I am on the Welcome Screen      # features/step_definitions/my_first_steps.rb:1
    When I touch "3"                      # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    And I touch "+"                       # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    And I touch "2"                       # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    And I touch "="                       # calabash-cucumber-0.9.106/features/step_definitions/calabash_steps.rb:15
    Then I should see a "5" in the screen # features/step_definitions/sums_steps.rb:1
      No element found for query: view marked:'screen' text:'5' (RuntimeError)
      ./features/step_definitions/sums_steps.rb:2:in `/^I should see a "(.*?)" in the screen$/'
      features/sums.feature:10:in `Then I should see a "5" in the screen'

Failing Scenarios:
cucumber features/sums.feature:4 # Scenario: Sum 3+2 = 5

1 scenario (1 failed)
6 steps (1 failed, 5 passed)
0m7.339s

But … why??? I don’t understand anything … I have my view and he knows which is screen … or not. And here it is where a huge benefit comes as a side effect from using BDD, accessibility, we will create a nice and accessible app because it is the only way Calabash can identify the views. So let’s do it, let’s put ‘screen’ as accessibility label in Xcode for the label we are going to use as screen.

Set accessibility label as “screen”

Don’t forget to Clean (⇧⌘K) and Build (⌘B) after each IB change to see the results in your tests.

Still getting the same result? Let’s see why. We were looking for a view marked:‘screen’ text:‘#{arg1}’, in this case view marked:’screen’ text:’5’, and we don’t have it. So, let’s pass our first test, put a 5 as the text of the “screen” label, Clean (⇧⌘K) and Build (⌘B) and “cucumber features/sums.feature” and Voilà!!!!.

First successful test

I know, I know, this is by far the less flexible and effortless possible solution but, and I want to be very clear on this point, you have to consider that BDD gives you the option and encourages to do the less code development necessary to pass the tests. As you can imagine requirements may change with time, I would say for sure they will, and the more complicated your development is, the more effort will be required to change it and still be passing the rest of tests so, if putting a 5 in the label passes the test, that’s all you have to do.

Step 4: Go through all your features and scenarios to create your App

At this point after completing the three previous steps you are a BDD master, and probably want too have something more useful than an app that shows a 5 in the screen no matter which number you press. To do it, and following BDD what we will do is go back to our feature file and add a new requirement that was in the initial text. In this case adding a new requirement, as long as we are in the same feature it means to add a new scenario.

Your sums.feature file should look like this:

Feature: Sums 
  In order to avoid mistakes users must be able to calculate a sum

  Scenario: Sum 3+2 = 5
    Given I am on the Welcome Screen
    When I touch "3"
    And I touch "+"
    And I touch "2"
    And I touch "="
    Then I should see a "5" in the screen

  Scenario: Sum 4+5 = 9
    Given I am on the Welcome Screen
    When I touch "4"
    And I touch "+"
    And I touch "5"
    And I touch "="
    Then I should see a "9" in the screen

Of course you could have this from the beginning, but when starting with BDD it is a good practice to start adding tests one by one.

And here it is where the cycle of BDD starts by adding a test, developing the solution and adding new tests, etc …

You can download the source code from github or from bitbucket.

To follow the steps you can use the commits:

  • Step 1: git checkout 0c442d93
  • Step 2: git chechout 164b669
  • Step 3: git checkout 5f3c9920

Any comments, please send me an email to blog@guillemfernandez.com

Comments