Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
Announcing Ginkgo and Gomega: BDD-Style Testing for Golang

I’m happy to announce that Ginkgo, a BDD-style testing framework for Go, and its preferred matcher library Gomega are ready for public release. There’s a comprehensive feature list, on the GitHub READMEs and both projects have extensive documentation written up (Ginkgo and Gomega).

Here’s a quick taste of what a Ginkgo & Gomega test looks like, there are many more samples in the documentation:

Describe("ScoreKeeper", func() {
    var scoreKeeper *ScoreKeeper

    BeforeEach(func() {
        var err error
        scoreKeeper, err = NewScoreKeeper("Denver Broncos")
        Expect(err).NotTo(HaveOccured())
    })

    It("should have a starting score of 0", func() {
        Expect(scoreKeeper.Score).To(Equal(0))
    })

    Context("when a touchdown is scored", func() {
        BeforeEach(func() {
            scoreKeeper.Touchdown("Manning")
        })

        It("should increment the score", func() {
            Expect(scoreKeeper.Score).To(Equal(6))
        })

        It("should update the scoring player's stats", func() {
            Expect(scoreKeeper.Stats).To(HaveKey("Manning"))
            Expect(scoreKeeper.Stats["Manning"]["Touchdowns"]).To(Equal(1))
            Expect(scoreKeeper.Stats["Manning"]["Points"]).To(Equal(6))
        })
    })
})

And here’s (a screenshot of) the output of go test:

Ginkgo Test Runner

So, why write Ginkgo?

Google’s Golang treats testing as a first-class citizen. Go has builtin support for writing and running unit tests in the Xunit style. Go, however, does not come with an assertion/matcher library. Nor does it provide any of the higher-level testing constructs that those in the BDD school of testing have grown fond of. Go’s authors have made it clear that these omissions are intentional.

After spending some time writing tests the Go way, I quickly came to miss all the things about BDD that make BDD-style testing so expressive and productive: descriptive tests that can act as effective documentation, simple shared test set up and teardown, nested contexts, etc… Thankfully, writing a solid full-featured BDD testing framework and matcher library for Go turned out to be relatively straightforward: a testament to Go’s flexibility!

Ginkgo and Gomega are heavily influenced by Cedar (BDD for Objective-C) and Jasmine (BDD for Javascript). If you’re familiar with either you’ll feel right at home with Ginkgo.

So Go forth and BDD! I’m looking forward to your pull requests – especially for any new Gomega matchers that you might find useful.

Ginkgo Gomega

Comments
  1. Roger Peppe says:

    Not a comment on the functionality this provides, but…

    Please, oh please, don’t tell people to import packages as “.”!

    It pollutes the name space (importing gingko and gomega this way imports almost 60 names into the global namespace) and makes it hard for people not entirely familiar with the code to know what’s locally defined and what’s external. It might seem like a convenience you can’t bear to sacrifice, but it is really best to avoid it.

    In the project I work on, we started off using gocheck in this style, but have moved towards using a short package identifier alias instead (“gc” in our case), which works pretty well. For example http://bazaar.launchpad.net/+branch/juju-core/view/head:/utils/trivial_test.go

  2. Onsi Fakhouri says:

    Hey Roger,

    I’m happy to add a warning to that effect to the documentation. Yes, obviously, I’m encouraging people to merge Ginkgo and Gomega into the global namespace of their *tests*. And, yes this can be problematic should a name collision occur (which the compiler will immediately catch).

    But, pragmatically speaking, it is also phenomenally convenient and allows for very flexible and descriptive tests with better signal:noise. Practically speaking, I’ve been using Ginkgo and Gomega for over a month and have not once run into a conflict, but – of course – YMMV. For packages that conflict, a short identifier will suffice — but I’d rather that be the exception than the norm.

  3. Afaik import . exists specifically for tests, gocheck also uses it.

  4. […] source: BDD testing for golang: Ginkgo and Gomega […]

  5. Christian says:

    It’s a nice way to write unit tests, but it misses the point of BDD, or better “specification by example” (excellent book: http://www.manning.com/adzic/). Specification by example is about communication and collaboration with all stakeholders. BDD approaches like the ones in this article are no good way to communicate with non-technical persons.

    A Go implementation of Cucumber would be a lot more useful.

  6. Aram Hăvărneanu says:

    With proper imports you can chose to read code breadth-first instead
    of depth-first. Usually it’s important to see how something is used
    before reading how something is implemented. Proper imports expose
    this information locally; it’s obvious which identifier is local
    to the package and which is not. I can defer reading about other
    package until I am satisfied I understood all the information I
    need about the local one.

    Proper scoped naming is important for other reasons as well. Packages
    expose (usually small) interfaces, and a scoped name carries semantic
    meaning which can become familiar and idiomatic. An io.Reader or
    fmt.Printf is the same everywhere. A Reader or a Printf loses its
    familiar character. Not only the reader has to do extra work to
    find out what those are, but he he burdened by new, idiosyncratic
    information relevant only to that particular piece of code.

    Readers can learn about how a particular interface is to be used
    by investigating how it’s used in other places. With scoped imports,
    this is one grep away. With dot imports, I need syntactic analysis;
    it fails the grep test. Authors are also interested in how their
    code is used. They are also hindered by improper package usage.

    Please don’t take this away.

  7. Onsi Fakhouri says:

    @Christian: I agree that this is not BDD a-la Cucumber. I think that’s why we went with “BDD-style” for both Cedar and Jasmine. And, yes, the intent is not to communicate with non-technical stakeholders. The primary intent is to allow developers to write descriptive tests.

    @Roger: godocs are coming (in a few days). Godoc is optimized for API documentation not tutorial/narrative-style documentation. I wanted to get the latter out first.

    And as for the slippery-slope argument — let’s all take a deep breath. You don’t have to use “.” — I’ll add all sorts of warnings to the docs. I’ve found that the constant repetition of “ginkgo.” and “gomega.” (or “K.” and “M.”) in the tests adds unnecessary noise and stutter but that is a purely subjective statement and I’m not going to hold people to it!

  8. Michael Whatcott says:

    @Onsi – Very nice work with Ginkgo. I’m one of the authors of GoConvey (github.com/smartystreets/goconvey), which is very similar. I agree with your stance on not following the Cucumber/Gherkin BDD school of thought. I admit that if I had found Ginkgo a few months ago I might not have written GoConvey, but I’m happy with what we’ve come up with. Best of luck with your development of Ginkgo.

  9. […] testing in Go was a joy. HM9000 became something of a proving-ground for Ginkgo & Gomega and we’re happy to say that both projects have benefited mutually from the […]

  10. This is beautiful, some years ago I gave go a shot and started to write a BDD library (ginkgo was not out there) but I never finished it:https://github.com/gabrielfalcao/gspec#playing

    Great, great work with those libraries Onsi, this is a state-of-art!

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *