• Text Post

Cucumber-JVM 1.0.0

Today I am very excited to announce Cucumber-JVM 1.0.0.

Cucumber-JVM is a pure Java implementation of Cucumber, with native support for the most popular JVM languages: Java, Scala, Groovy, Clojure, Rhino, Jython and JRuby. Cucumber-JVM is the successor of Cuke4Duke, which was the Ruby implementation of Cucumber, running on JRuby. Cuke4Duke was a pain to use - it was hard to install and both slow and difficult to run.

Cucumber-JVM on the other hand is easy to install, and it’s fast and easy to run (thanks to its JUnit integration).

I will be giving an introduction to Cucumber-JVM at CukeUp! on April 4, and I am also working on documentation, but for now let me give you a quick glance of what you can do with it. We are going to create the following files:

.
|-- build.xml (Optional)
|-- pom.xml (Optional)
`-- src
    |-- main
    |   `-- java
    |       `-- cucumber
    |           `-- examples
    |               `-- java
    |                   `-- helloworld
    |                       `-- Hello.java
    `-- test
        |-- java
        |   `-- cucumber
        |       `-- examples
        |           `-- java
        |               `-- helloworld
        |                   |-- HelloStepdefs.java
        |                   `-- RunCukesTest.java
        `-- resources
            `-- cucumber
                `-- examples
                    `-- java
                        `-- helloworld
                            `-- helloworld.feature

Start by creating helloworld.feature:

Feature: Hello World
  Scenario: Say hello
    Given I have a hello app with "Howdy"
    When I ask it to say hi
    Then it should answer with "Howdy World"

Now, create a pom.xml if you want to use Maven or a build.xml if you want to use Ant. This is all you need to download Cucumber-JVM and run your features.

Next, create RunCukesTest.java which is used to run features from JUnit:

package cucumber.examples.java.helloworld;

import cucumber.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@Cucumber.Options(format = {"pretty", "html:target/cucumber"})
public class RunCukesTest {
}

We are passing some options to Cucumber, telling it to generate a HTML report as well.

When you run ant download runcukes or mvn test you will see all of your steps showing up as undefined. Cucumber-JVM will print some snippets to get you started. Let’s add those snippets to HelloStepdefs.java and fill in the blanks:

package cucumber.examples.java.helloworld;

import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;

import static org.junit.Assert.assertEquals;

public class HelloStepdefs {
    private Hello hello;
    private String hi;

    @Given("^I have a hello app with \"([^\"]*)\"$")
    public void I_have_a_hello_app_with(String greeting) {
        hello = new Hello(greeting);
    }

    @When("^I ask it to say hi$")
    public void I_ask_it_to_say_hi() {
        hi = hello.sayHi();
    }

    @Then("^it should answer with \"([^\"]*)\"$")
    public void it_should_answer_with(String expectedHi) {
        assertEquals(expectedHi, hi);
    }
}

Finally we need an implementation of our Hello World system in Hello.java:

package cucumber.examples.java.helloworld;

public class Hello {
    private final String greeting;

    public Hello(String greeting) {
        this.greeting = greeting;
    }

    public String sayHi() {
        return greeting + " World";
    }
}

Run Ant or Maven again, and all is green. If you would rather do all of this in Scala, Groovy, Clojure, Rhino, Jython, JRuby - or even Ioke - that’s easy too. You will find more examples here.

Some other features of Cucumber-JVM:

  • Multiple output formats: HTML, JSON, JUnit and more.
  • DI support: PicoContainer, Guice, Spring, Weld and OpenEJB.
  • Automatic conversion of step definition arguments.
  • I18n support for over 40 spoken languages
  • Grails and Play support on its way.
  • IntelliJ support is on the way.

Take it for a spin and let us know what you think!

• Text Post

Replacing NPM with Make

Package management at a high level is a fairly simple concept. A software package can be uploaded to—and downloaded from—a central location.

The Node.js Package Manager NPM does this, and a whole lot more. If you run npm help you’ll be presented with 64 different commands. I have been using NPM for about a year, and I have only ever used 4 or 5 of these. If someone did a study of NPM and who uses what commands I expect they would find a power-law relationship.

As you might expect from a feature-rich tool like this, the codebase is significant. Almost 10.000 lines of code spread across over 100 files according to CLOC. 1.800 issues have been closed since the project’s inception, and there are 100 open ones. These numbers illustrate that NPM is a very complex piece of software.

If all you need is uploading and downloading files there must be a simpler way.

It should Just Work

I work in a place where we use a lot of different programming languages. It’s important that a developer can clone a git repository and have the code “just work” without the need to learn and install a lot of additional software.

The ruby ecosystem is notoriously bad about this. There are many incompatible implementations of ruby. Then there are tools like rvm, bundler and rubygems. For someone who only occasionally works with Ruby this is a huge barrier, especially since there are so many moving parts and things tend to break nilly willy.

One of the really nice things about Node.js is that the executable is a single node binary with everything inside it. We often add a precompiled node binary to our git repositories. This removes a lot of tool complexity, and we reduce the risk of developers using different (and incompatible) versions of Node.js. This is especially important for a young project like Node.js where the APIs change frequently.

Node.js 0.6.3 and newer bundle NPM. This doesn’t mean NPM is bundled inside the node binary. Remember - NPM is a hundred files. Checking in NPM alongside node isn’t quite as convenient. If all you need is to pull down NPM packages there is a much simpler solution:

Make

Downloading NPM packages with Make and cURL

Below is a typical Makefile from one of the Node.js projects I work on. It pulls down NPM modules from the NPM registry as well as alternative locations. We sometimes pull them from a github tag, sometimes from an internal HTTP server (for our proprietary modules).

node_modules: Makefile
    @rm -rf $@
    @mkdir -p $@
    $(call get_src_module,$@,\
    https://github.com/tastapod/node-imap/tarball/bruno-merge)
    $(call get_npm_module,$@,log,1.2.0)
    $(call get_npm_module,$@,connect,1.8.2)
    # We have to manually fetch connect's dependencies
    $(call get_npm_module,$@,qs,0.4.0)
    $(call get_npm_module,$@,mime,1.2.4)
    $(call get_npm_module,$@,formidable,1.0.8)
    @touch $@

get_npm_module = $(call get_node_module,$1,$2,\
    http://registry.npmjs.org/$2/-/$2-$3.tgz,package)

get_src_module = $(call get_node_module,$1,$2,$3,)

get_node_module = @set -e; mkdir -p $1/$2; \
    echo "Fetching module $2 "; \
    curl -L --silent $3 | tar xzf - \
    --strip=1 --directory=$1/$2 $4

You can find the code in this gist (with tabs intact).

Publishing NPM packages with Make and scp

We have some proprietary Node.js libraries that we make available on a HTTP server. We considered installing our own NPM Registry Server, but quickly decided that this was more complex than it needs to be.

We settled for an nginx server and scp for uploading packages. Make to the rescue again:

NAME    := $(shell node -e "console.log(JSON.parse(require(\
'fs').readFileSync('package.json', 'utf8')).name)")
VERSION := $(shell node -e "console.log(JSON.parse(require(\
'fs').readFileSync('package.json', 'utf8')).version)")
TARBALL := $(NAME)-$(VERSION).tgz

npm-publish:
    @rm -Rf package
    @mkdir package
    @cp -R lib package/lib
    @cp package.json package
    @tar czf $(TARBALL) package
    @scp $(TARBALL) npm@npm:/home/npm/repo

clean:
    rm -Rf *.tgz

.PHONY: npm-publish clean

You can find the code in this gist (with tabs intact).

Conclusion

I really appreciate the hard work that goes into the Node.js ecosystem, including NPM. I just wish things were simpler.

Thanks to Joe Walnes for coming up with the ingenious idea to download NPM packages with Make and cURL and Dan North for showing me.

• Text Post

The training wheels came off

Cucumber rounded the 1,000,000 download mark a couple of days ago, and is clearly a very popular tool. It owes a lot of its popularity to Cucumber-Rails - a Ruby gem that sets up Cucumber in a Rails project. One of the reasons Cucumber-Rails has become popular is that it is relatively easy to get started with.

Most people who learned to ride a bike as a child had training wheels. When a child learns to ride on his or her own, the training wheels are removed. Until last week, Cucumber-Rails also came with pre-mounted training wheels, in the form of a generated web_steps.rb file with 30 or so reusable step definitions.

This gave a lot of people a flying start with Cucumber and Rails. Many people never removed the training wheels. Instead they soldered them to the frame by piling up with long, verbose and brittle scenarios that depend on them.

Half a year ago we added a warning to the generated web_steps.rb, because relying on them has so many negative effects.

Some people followed this advice, but there are still a lot of people who fall into the trap. In Cucumber-Rails 1.1.0 they were removed for good, and in 1.1.1 we also removed its tricycle cousin - the cucumber:feature generator. The training wheels came off.

The training wheels came off

The reactions were exactly as I had expected. -A combination of applause and gnashing of teeth. Most of the people who disagree say something along the lines of:

This is going to make it harder for people to get started with Cucumber.

I say: this is going to make it harder for people to use Cucumber badly. Now they have to:

  1. Learn the Capybara API instead of the web_steps.rb regular expressions.
  2. Think harder about what goes into a scenario.

If this hurts the adoption of Cucumber-Rails I’m perfectly fine with it. You already have plenty of rope to hang yourself with, and I’m not going to tie the noose for you.

Let me explain why web_steps.rb is a terrible, terrible idea.

Boring scenarios

Cucumber was designed around the core principles of BDD, and one of these principles is to improve stakeholder collaboration through a ubiquitous language. This essentially means that both code and executable specifications (Cucumber scenarios) should be written in the language of the domain. The “domain” is defined by the value the stakeholders and users hope to achieve with the software. This can be booking a ticket or sharing pictures with friends or an infinite number of activities. Clicking links and buttons or filling in text fields has nothing to do with the domain.

Cucumber scenarios that consist of 10 or so steps that click links, fill in fields, push buttons and look for text are going to bore your stakeholders to death.

Their eyes will glaze over, and they won’t even spot mistakes. Even programmers will have a hard time spotting conceptual errors at this abstraction level. Using Cucumber exclusively to emulate a keyboard and a mouse is possible, but it’s not what it was designed for.

If all you need is a testing tool for driving a mouse and a keyboard, don’t use Cucumber. There are other tools that are designed to do this with far less abstraction and typing overhead than Cucumber. Capybara DSL and Steak are much better if you want a programmer/tester-only tool.

Brittle scenarios

Allowing technical details to bleed into scenarios does more harm than losing stakeholder involvement through boredom. It makes everything harder to change as well. Consider this scenario for logging in:

Scenario: Successful login
  Given a user "Aslak" with password "xyz"
  And I am on the login page
  And I fill in "User name" with "Aslak"
  And I fill in "Password" with "xyz"
  When I press "Log in"
  Then I should see "Welcome, Aslak"

If users have to log in there is usually a lot of functionality that is only accessible to users who have logged in. This means logging in has to happen before most scenarios:

Background: A logged in user
  Given a user "Aslak" with password "xyz"
  And I am on the login page
  And I fill in "User name" with "Aslak"
  And I fill in "Password" with "xyz"
  When I press "Log in"
  Then I should see "Welcome, Aslak"

You’ll have to repeat this in all of your scenarios that describe functionality for logged in users. When someone decides to allow users to log in with an email address instead of a user name we have to go over all of our scenarios and change them.

It’s not a question of if the user interface has to change, but when. Usually a UI change has far wider consequences than this example.

Where is my workflow?

Cucumber was designed to help developers with TDD at a higher level. A common challenge with conventional TDD is that developers don’t know where to start. It’s hard to figure out what tests to write.

The idea with Cucumber (and BDD in general) is that stakeholders assist in writing scenarios - or executable specifications. This solves the where do we start problem with TDD. The scenarios express what a user should be able to do, and not how. When a scenario is defined, programmers implement the required functionality.

This kind of workflow is much harder to follow when scenarios are written in a low-level, imperative style. Very few stakeholders or business analysts are going to agree to defining functionality in terms of mouse clicks and key presses. They think and talk at a higher abstraction level, and scenarios should capture that.

I don’t care about this tree hugging stuff, give me my web_steps.rb

When I started the Cucumber project in 2008 I had three major goals:

  • Help stakeholders express what they want via executable specifications
  • Help programmers write better software by making TDD/BDD easy
  • Reduce misinterpretations through a ubiquitous language

Scenarios based on web_steps.rb undermine those goals, and that is why I decided to remove them. Maybe it’s a pride thing. -Like the shopkeeper who refuses to sell merchandise he believes is of bad quality, even if doing so would mean more customers.

Unfortunately, there are books, screencasts and tutorials out there that teach you Cucumber using web_steps.rb. If web_steps.rb disappeared for good this would harm the people who are selling this training material. People who have bought it won’t get what they paid for. So I present to you: cucumber-rails-training-wheels.

This is a stillborn project. I will not accept bug reports or pull requests. The only reason it exists is to make old tutorials and books work.

Fine. I still think it’s easier to write scenarios based on web_steps.rb

Which one of these lines are easier to write?

When I press "Log in"
click_button("Log in")

I don’t think it’s harder to read the Capybara API than the regular expressions in web_steps.rb. If it is, someone needs to improve the Capybara API docs.

Can you give me an example of the new way?

Let’s take the login scenario above and make it a little more readable:

Scenario: User is greeted upon login
  Given the user "Aslak" has an account
  When he logs in
  Then he should see "Welcome, Aslak"

The step definition for the first step would create a new User record and store a reference in a @user variable. This would use ActiveRecord directly. The interesting part is logging in. Cucumber prints out snippets of code for undefined steps:

When /^he logs in$/ do
  # express the regexp above with the code you wish you had
end

Assuming we know what the log in screen is supposed to look like, we can implement this step definition:

When /^he logs in$/ do
  visit('/login')
  fill_in('User name', :with => @user.name)
  fill_in('Password', :with => @user.password)
  click_button('Log in')
end

That wasn’t so hard. Now let’s improve on that Background we had earlier so we can log in before other scenarios:

Background: The user is logged in
  Given a logged in user

Scenario: Upload a picture
  # Some steps here

When we’re describing other parts of the system that require login, the login details like user name, password and how to log in are only distracting. That is why we make it a one-liner. Let’s look at how we would define that:

Given /^a logged in user$/ do
  @user = User.create!(:name => 'Aslak', :password => 'xyz')
  visit('/login')
  fill_in('User name', :with => @user.name)
  fill_in('Password', :with => @user.password)
  click_button('Log in')
end

Can you spot the duplication with the When /^he logs in$/ step definition? Let’s improve this:

module LoginSteps
  def login(name, password)
    visit('/login')
    fill_in('User name', :with => name)
    fill_in('Password', :with => password)
    click_button('Log in')
  end
end

World(LoginSteps)

Now your two step definitions can be simplified:

When /^he logs in$/ do
  login(@user.name, @user.password)
end

Given /^a logged in user$/ do
  @user = User.create!(:name => 'Aslak', :password => 'xyz')
  login(@user.name, @user.password)
end

Not only have you made your Scenario and Background easier to read, you also isolated the login details in one single place. Changing the login process to use an email instead of a name will be easy. No scenarios have to change, and you only have to change a couple of places in your step definitions.

Conclusion

Removing the web_steps.rb training wheels makes Cucumber harder to use badly. You have to learn the Capybara API instead of regular expressions, and you will take more advantage of the snippets Cucumber prints for undefined steps. This also means you have to think in terms of the domain and not the user interface when you write scenarios. This makes them a lot easier to maintain. Short, declarative scenarios serve as easily readable documentation, and non-technical stakeholders and business analysts are more likely to get intimate with them.

There are also a couple of things you no longer have to do:

  • Wade through web_steps.rb and try to make your steps fit their mold. (You’re in charge and can say what you want)
  • Update a cryptic paths.rb or selectors.rb file
  • Be afraid to change generated code you don’t really understand

Here are some great resources for more information:

Happy cuking!

• Text Post

Webbit 0.2.0 with hybi-10 support

The WebSocket specification has gone through several drafts, and seems to be settling down after some security flaws were identified and resolved a couple of months ago. Most current web servers that support WebSockets implement the hybi-00 version of the specification (which, confusingly is the same as hixie-76).

Last week, Google released Chromium 14.0.835.2, which implements hybi-10 - the latest draft of the WebSocket specification. This version of Chromium will not be able to talk to WebSocket servers that only implement the older WebSocket specifications.

Chromium is mostly used by programmers like myself who want early access to the new features, so this isn’t going to be a problem for Chrome users yet. Chrome is based on Chromium, and it auto-updates itself in the background. This means that one day in the near future a lot of WebSocket apps will break for Chrome users.

Web applications based on Webbit 0.2.0 will not have this problem. Webbit is a light-weight Java web server with WebSocket and EventSource support, created by my colleague Joe Walnes. I have been a contributor to Webbit almost since the beginning, and the past couple of days I have implemented hybi-10 support. Webbit now supports hybi-10, hybi-0/hixie-76 and hixie-75.

One of the exciting features of the new protocol specification is the ability to send and receive binary data over a WebSocket. Previous versions of the specification only allowed UTF-8 encoded strings.

On the browser side, this is possible via JavaScript Typed Arrays. Typed arrays are JavaScript types that are available in modern browsers, and provide an API similar to Node.js’ Buffer type. In short, this allows JavaScript code to work with binary data, reading and writing signed or unsigned numbers with 8, 16, 32 or 64 bits. This opens up for transfer of richer data types, such as audio and video, but also custom protocols. Chromium doesn’t support binary data over WebSockets yet, but it will soon and Webbit is ready for it.

Grab a copy of Webbit today and ask questions on the webbit mailing list. -And if you happen to be in Melbourne or Brisbane in December, join me for an in-depth Webbit presentation at the YOW! conference.

• Photo Post

So you have decided to learn to use Cucumber on your next project. You head to the Cucumber Wiki, but you still feel a little lost.

We don’t want anyone to be lost, so Matt and I have written The Cucumber Book. Well, 3/4 of it at least. You can buy the beta book today!

• Text Post

Cucumber 1.0.0

Cucumber

I am so thrilled about this I set up a blog!

Today I released Cucumber 1.0.0 after three years in the making. Here are some interesting numbers:

What’s next? I am working on a Cucumber book with Matt Wynne that will be out later this year. There is a Javascript port underway that will work both on Node.js and in browsers. When I’m done with the book I will pick up the work on a pure Java implementation that will supersede Cuke4Duke.

I would like to thank everybody on the Cucumber Google group, everybody who has reported bugs, showed it off at their companies or local user groups or promoted it in general. To the contributors who made it into git - thanks so much for giving your time and code. -And the core team, Matt Wynne, Gregory Hnatiuk, Mike Sassak, Joseph Wilk and Ben Mabey. You are awesome.