‹‹ All posts

BDD with Gherkin in Go language (golang)

10 of February, 2016


BDD and Gherkin is very useful for realising what software is meant to do. Those business friendly user stories also are very good to use for modelling the domain of system. A while ago I was happy to learn that you can do it in golang too.

There is this awesome tool called godog, which was build by @l3pp4rd this summer. It uses cucumber’s gherkin parser gherkin-go. It adds a simple runner on top of it, which fits neatly into story TDD cycle.

So if the output of your example workshop is feature like

Feature: three for two stock clearance sale
  In order to clear the stock of old items
  As a store manager
  I want customer to get a promotion of three items for the price of two

  Scenario: buyer gets third sale item for free
    Given there is on sale bicycle "Kangaroo 3000" which costs 299 pounds
    When I add three "Kangaroo 3000" bicycles into the basket
    Then I should get third bicycle for free
    And the basket total should be 598 pounds

You can easily inforporate it into your development with godog.

First you’ll have to install it with

go get github.com/DATA-DOG/godog/cmd/godog

Then, assuming your feature file is at features/three-for-two-sale.feature you can generate boilerplate code by just running godog from parent directory. It will detect thefeature files and will output something similar to

$ godog
Feature: three for two stock clearance sale
  In order to clear the stock of old items
  As a store manager
  I want customer to get a promotion of three items for the price of two

  Scenario: buyer gets third sale item for free                           # features/domain.feature:6
    Given there is on sale bicycle "Kangaroo 3000" which costs 299 pounds
    When I add three "Kangaroo 3000" bicycles into the basket
    Then I should get third bicycle for free
    And the basket total should be 598 pounds

1 scenarios (1 undefined)
4 steps (4 undefined)
916.933µs

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

func thereIsOnSaleBicyclewhichCostsPounds(arg1 string, arg2 int) error {
	return godog.ErrPending
}

func iAddThreebicyclesIntoTheBasket(arg1 string) error {
	return godog.ErrPending
}

func iShouldGetThirdBicycleForFree( ) error {
	return godog.ErrPending
}

func theBasketTotalShouldBePounds(arg1 int) error {
	return godog.ErrPending
}

func featureContext(s *godog.Suite) {
	s.Step(`^there is on sale bicycle "([^"]*)" which costs (\d+) pounds$`, thereIsOnSaleBicyclewhichCostsPounds)
	s.Step(`^I add three "([^"]*)" bicycles into the basket$`, iAddThreebicyclesIntoTheBasket)
	s.Step(`^I should get third bicycle for free$`, iShouldGetThirdBicycleForFree)
	s.Step(`^the basket total should be (\d+) pounds$`, theBasketTotalShouldBePounds)
}

You can just copy-paste generated code to your test file discount_test.go and with next run godog will suggest you what to implement

$ godog
Feature: three for two stock clearance sale
  In order to clear the stock of old items
  As a store manager
  I want customer to get a promotion of three items for the price of two

  Scenario: buyer gets third sale item for free                           # features/domain.feature:6
    Given there is on sale bicycle "Kangaroo 3000" which costs 299 pounds # main.thereIsOnSaleBicyclewhichCostsPounds
      TODO: write pending definition
    When I add three "Kangaroo 3000" bicycles into the basket
    Then I should get third bicycle for free
    And the basket total should be 598 pounds

1 scenarios (1 pending)
4 steps (1 pending, 3 skipped)
1.501702ms

To pass the step you have to make it return null, to fail - return error.

If you need to pass state in between your steps, then you can create a Context struct, store state there and assign all the steps to it.

Being very young, godog is not without quirks or issues, but is very usable and saves loads of time if you are used to develop in this kind of way.

See full docs at official repo.

comments powered by Disqus