Asymmetrical View

How We Run Cucumber

Cucumber is a wonderful behavior driven development tool by Aslak Helles√ły. There is a getting started guide in the wiki at github that describes how to get it set up and running.

We’ve written a wrapper around Cucumber to help make it easier to run along with our application and to make it less intrusive when it runs the browser (at least under Linux).

Server Execution

Most of our test driven development doesn’t require script/server to be running the web application, and we want it to run under either the cucumber or test rails environment when it does. Stopping (if it’s running) the development server, starting it and then shutting it down again when the tests are done was a manual process that we automated.


When we run Cucumber under X Windows, it often grabs focus and keeps us from doing anything else with the desktop while the tests are running. This is annoying to say the least. Thankfully X11 has a utility called Xnest which allows you to run a window which is a contained X desktop. Running this and then telling the browser to run inside it keeps it out of our way and allows us to keep using the machine without being constantly interrupted by the browser constantly jumping to the foreground.

script/server Arguments

To pass arguments (such as the port, or other options) through to script/server, put a -- between the arguments to script/cucumber-runner and they will be passed on verbatim to script/server. In this example, -p 8080 will be passed to script/server instructing it to use port 8080.

$ script/cucumber-runner -g 1024x768 -- -p 8080


#!/usr/bin/env ruby
require 'optparse'

# Controller for running Cucumber feature tests on your Rails application.
# Supports stopping/starting WEBRick in cucumber or test rails environment and
# (on supporting systems, eg: Linux) running the browser under Xnest to keep it
# away from your other desktop activities.
# Author::     Kyle Burton <>
# Copyright::  Copyright (c) 2010 Kyle Burton
# License::    Distributes under the same terms as Ruby

# Command line runner.
class CucumberRunner

  # location of the rails scripts
  SCRIPT_ROOT = File.dirname(__FILE__)

  # Set up defaults, can be overridden with command line parameters.
  def initialize
    @opts = {
      :env             => 'cucumber',
      :geometry        => '1280x800',
      :display         => ENV['DISPLAY'],
      :xnest_display   => ':2',
      :control_webrick => true,
      :try_use_xnest   => true

  # Determine if Xnest is present, and if it should be used (Not on OS X).
  def use_xnest?
    return false unless @opts[:try_use_xnest]
    on_darwin = (`uname` =~ /Darwin/)
    has_xnest = !(`which Xnest`.empty?)
    !on_darwin && has_xnest

  # Start Xnest in the background, save off the pid so it can be stopped later.
  def start_xnest
    @opts[:display] = @opts[:xnest_display]
    cmd = "Xnest #{@opts[:xnest_display]} & echo $!"
    @xnest_pid = `#{cmd}`.to_i

  # Stop Xnest with a SIGTERM.
  def stop_xnest
    Process.kill("TERM", @xnest_pid) if @xnest_pid

  # Stop the WEBRick server by looking for it in the process tree.
  def stop_webrick
    res = `ps aux | grep [r]uby | grep [s]cript/server`
    pid = res.split[1]
    return unless pid
    puts "#{$0} STOPPING WEBRick pid=#{pid}"
    Process.kill "KILL", pid.to_i

  # Start WEBRick with the configured rails environment as a daemon (background).
  def start_webrick
    cmd = "#{SCRIPT_ROOT}/server -e #{@opts[:env]} -d"
    puts "#{$0} Starting WEBRick: #{cmd}"
    system cmd

  # Process any command line arguments.
  def parse_opts do |opts|
      opts.banner = "Usage: #{$0} [options]"

      opts.on("-h", "--help") do
        puts <<-EOH
       #{$0} [[opts]]

        -e ENV  --envrionment ENV   Rails environment to run under default=#{@opts[:env]}
        -g GEO  --geometry GEO      Xnest geometry to use default=#{@opts[:geometry]}
        -X      --no-xnest          Do not use Xnest (even if present)
        -d DSP  --display DSP       DISPLAY to use default=#{@opts[:display]}
        -x DSP  --xnest-display DSP Xnest's DISPLAY to use default=#{@opts[:xnest_display]}
        -W      --no-webrick        Don't start WEBRick (assume running) default=false
        exit 0

      opts.on("-e", "--envrionment ENV") do |env|
        @opts[:env] = env

      opts.on("-g", "--geometry GEO") do |geo|
        @opts[:geometry] = geo

      opts.on("-X", "--no-xnest") do
        options[:use_xnest] = false

      opts.on("-d", "--display DSP") do |dsp|
        options[:display] = dsp

      opts.on("-x", "--xnest-display DISP") do |disp|
        options[:xnest_display] = disp

      opts.on("-W", "--no-webrick") do
        options[:control_webrick] = false

  # Process options, start Xnest, [re]start WEBRick, execute the cucumber
  # suite, then stop Xnest and stop WEBrick
  def run
    start_xnest if use_xnest?

    if @opts[:control_webrick]

    cmd = "#{SCRIPT_ROOT}/runner #{SCRIPT_ROOT}/cucumber #{ARGV}"
    ENV['DISPLAY']   = @opts[:display]
    ENV['RAILS_ENV'] = @opts[:env]
    puts "#{$0} using RAILS_ENV=#{ENV['RAILS_ENV']}"
    res = system cmd

    stop_webrick  if @opts[:control_webrick]
    stop_xnest    if @xnest_pid

  def self.main


You can download or check out cucumber-runner from my github cucumber-example project.

Running Cucumber with this wrapper helps make it easier and less intrusive to use. If anyone has suggestions for how to make it less intrusive while running under OS X, please email me, I’d love to hear your suggestions.

Kyle Burton, 10 Jun 2010 – Philadelphia PA

Tags: cucumber,ruby,testing