This month Sittercity Tech has released a new project on GitHub: gocumber!

So what is gocumber (besides a goofy name)? Gocumber is a package written in Go that is used for parsing and executing Gherkin. It was created while we were writing our first Go service here at Sittercity. Perhaps unsurprisingly based on its name it is an attempt to build a Cucumber-like tool for Go.

To understand why it was necessary it will help to understand a bit about how we develop.

Why do we need this?

Sittercity is a very opinionated TDD shop. We believe very strongly in the test-first mantra. What this means in practice while developing a project is:

  1. We write Gherkin features as a group to lay out our desired behavior. This is done before any code is written or even a git repository is initialized.
  2. We then set up our project and pull in all of our desired libraries
  3. Next we begin implementing the Gherkin steps until we can run our features (with failures since nothing is implemented)
  4. Lastly we start implementing in code

The last step there also involves unit testing but I’ll leave that out for the time being. Rest assured no code is written until we have a lot of failing tests.

Okay, so you like to test. Now what?

All of this meant that the first order of business after our Gherkin features were written was picking our testing tools. The go standard library has a pretty robust testing package that seemed to offer what we needed but we quickly realized that there was nothing out there that provided what we needed for our Gherkin features.

Currently at Sittercity we mostly have applications written in Ruby. This means that most of our other projects use cucumber. But since we are expanding into Go we needed some way to parse and execute our Gherkin features. We found a few options but they were either not actively developed or half-implemented. We decided to take a first stab at implementing what we needed ourselves and see where it took us.

For starters we needed some way to parse the Gherkin itself. Luckily we found the go-gherkin package from muhqu. This allowed us to concentrate on creating an interface to execute steps and access variables.

Gocumber Example

So what does this interface look like in code? Let’s start with some simple gherkin:

Feature: gocumber example feature
  As a person wanting to learn about gocumber
  I want to be shown a bunch of awesome examples

  Scenario: Deactivate a user
    Given I have an existing user with the name "Cool Dude"
    When I deactivate the user named "Cool Dude"
    Then the user "Cool Dude" should be deactivated

Now we need to implement the steps listed above. We would create a file named ‘example_feature_test.go’ and set it up like a standard Go test:

import "testing"
import "github.com/sittercity/gocumber"

func TestYourStuff(t *testing.T) {
  steps := make(gocumber.Definitions)

  steps.Given(`I have an existing user with name "(.*)"`, func(matches []string, _ gocumber.StepNode) {
    // your code to create a user, you can use 'matches[1]' to pull out the
    // name, like so: user_name := matches[1]
  })

  steps.When(`I deactivate the user named "(.*)"`, func(matches []string, _ gocumber.StepNode) {
    // your code to deactivate the specific user found in 'matches[1]'
  })

  steps.Then(`the user "(.*)" should be deactivated`, func(matches []string, _ gocumber.StepNode) {
    // your code to check that the user in 'matches[1]' is deactivated
  })

  steps.Run(t, "example.feature")
}

This is a contrived example but you can see the basics. Here we create the step definitions and implement our desired behavior. If you forget to implement a step then you’ll receive an error when running your tests, just like in Cucumber. All of the steps are then executed at the end with the ‘step.Run()’ function.

You can see a more complete example in our git repository under the ‘example’ directory.

Now we have a gherkin tool to execute our tests! We were off and running. We’ve successfully implemented our first Golang project and are spinning up a few more. In the near future we’ll be rolling this tool into multiple projects, following much the same pattern as above.

What’s missing?

So now that the tool is available where do we go from here? Well, we have a few missing pieces of functionality that we have not yet needed to use internally and so have not implemented. The main things that we are looking to add:

  1. We currently rely on the standard Go test framework to execute the tests. We would like to have a purpose-built feature runner like cucumber is for ruby.
  2. Error display is still a bit rough. Sure, it catches the errors but it can be difficult to visually parse what is going wrong.

We plan to continue adding to the project but we strongly believe in only engineering a solution when the need arises so we’re not in any rush.

We would love to hear feedback! Feel free to file issues and/or provide PRs to add functionality.

P.S. - I don’t remember how we came up with this terrible name. I imagine it was said as a joke at first but then stuck!