Basic Cucumber feature testing

Cucumber is a Behaviour-Driven-Development (BDD) tool. You can use to automate the acceptance tests for your software systems. A real-world example of its use in a large application is the MediaWiki QA process.

This post will show you the steps to get it up-and-running to test a trivial app on a Unix (Mac, Linux) computer. I’ll assume that you already have Ruby installed.

First up, install Cucumber’s Ruby implementation:

$ sudo gem install cucumber
$ sudo gem install rspec

If you’re on Debian, you can also achieve this with apt-get:

$ sudo apt-get install ruby-cucumber-core ruby-rspec

The versions that I got from the install were-

$ ruby --version
ruby 2.2.3p173 (2015-08-18) [x86_64-linux-gnu]
$ cucumber --version
2.3.0

Make a “hello world” project:

$ mkdir cucumber-hello
$ cd cucumber-hello/

One of the under-celebrated features of Cucumber is the quality of its error messages. Simply attempt to run it and you will be told what to do next:

$ cucumber
No such file or directory - features. You can use `cucumber --init` to get started.

Go ahead and run cucumber --init as the program suggests:

$ cucumber --init
  create   features
  create   features/step_definitions
  create   features/support
  create   features/support/env.rb

This has set up your project. In the same vein as Test-Driven Development (TDD), the usual practice is to write the tests before you code.

Most programmers will be familiar with the expected output of a “Hello World” program. In Cucumber, this ‘feature’ would be represented in Cucumber as:

Feature: Test

  Scenario: Hello
    When I run the "hello-world" program
    Then I should see "Hello World"

Save this definition to features/hello.feature in the project directory and attempt to run Cucumber again:

$ cucumber
Feature: Test

  Scenario: Hello                        # features/hello.feature:3
    When I run the "hello-world" program # features/hello.feature:4
    Then I should see "Hello World"      # features/hello.feature:5

1 scenario (1 undefined)
2 steps (2 undefined)
0m0.007s

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

When(/^I run the "([^"]*)" program$/) do |arg1|
  pending # Write code here that turns the phrase above into concrete actions
end

Then(/^I should see "([^"]*)"$/) do |arg1|
  pending # Write code here that turns the phrase above into concrete actions
end

The output helpfully contains the skeleton code for writing the test steps in Ruby. Using this as a base, I implemented this using the rspec expectations syntax, to check if the string starts with “Hello World”.

When(/^I run the "([^"]*)" program$/) do |cmd|
  @value = `./#{cmd}`  
end

Then(/^I should see "([^"]*)"$/) do |val|
  expect(@value).to start_with(val)
end

Save these steps to features/step_definitions/hello_steps.rb

Finally, its time to code. Write up an implementation of “Hello World” in basically any available programming language, and save the output to an executable file called hello-world:

Using bash:

#!/bin/sh
echo "Hello World"
$ chmod +x hello-world

Manually testing:

$ ./hello-world
Hello World

Automatically testing with Cucumber confirms that the test criteria are met:

$ cucumber
Feature: Test

  Scenario: Hello                        # features/hello.feature:3
    When I run the "hello-world" program # features/step_definitions/hello_steps.rb:1
    Then I should see "Hello World"      # features/step_definitions/hello_steps.rb:5

1 scenario (1 passed)
2 steps (2 passed)
0m0.016s

Now that you’ve completed these steps, you should have this project structure:

$ find .
.
./features
./features/support
./features/support/env.rb
./features/step_definitions
./features/step_definitions/hello_steps.rb
./features/hello.feature
./hello-world

Next steps

Our scenario for the Hello World program has users interfacing with the system entirely with non-interactive shell commands. Cucumber needs to be able to observe the external behaviour of your application, so your steps will end up including some powerful test libraries. Some that are used often are:

Leave a Reply

Your email address will not be published. Required fields are marked *