Skip to content

History of given

jimweirich edited this page Aug 30, 2012 · 2 revisions

Ruby Hoedown (2009?)

A bunch of folks from EdgeCase were attending the Ruby Hoedown conference (in 2009 I think) and were sitting around a table near the back of the room. My mind was wandering during some of the talks, thinking about how to do testing better. I really like the Given/When/Then approach in cucumber, but the heavy-weight step definitions were too much for simple unit testing. I wanted a DSL-like syntax that really reflected the nature of Ruby.

So I grabbed a piece of paper, sketched out some code samples on it and passed it around the table for comment. I merely asked "If you were to see a test written out like this, could you figure out what was going on"? I got lots of feedback and ideas from the process.

My favorite feedback was from Joe O'Brien who turned to me and asked in a serious voice "You're not really thinking of writing another test framework in Ruby, are you?" I assured him I had no intention of doing that and was just exploring some ideas.

Initial Versions

Over the next year I played with a project called Given on and off. It was built on top of Test::Unit and was fairly heavy-weight. I played with the syntax a bit and experimented with capturing exceptions. It was never used in a real project (to my knowledge), but the experimentation was a big help in understanding what I was looking for in a Given/When/Then library.

Wrong Directions

I dropped the Given project for a while and experimented with some ideas from the Wrong library (https://github.com/sconover/wrong) from Alex Chaffee. I had a working prototype built, but never got around to integrating the ideas back into Given.

Introducing RSpec

At some point in time I saw Jon Larkowski given his "Pure RSpec" talk and I was introduced to some of the more interesting features of RSpec. This was the first time I saw the "let" syntax and fell in love with it. As I started using RSpec I realized that RSpec mapped almost perfectly into my ideas for Given/When/Then.

  • Given ==> before
  • Given(:var) ==> let(:var)
  • When ==> before
  • When(:result) =>> let!(:result)
  • Then ==> specify

When I realized this, I abandoned the old heavy-weight Test::Unit implementation and created the rspec-given library what was just a thin wrapper of a few aliases around what RSpec. The result was an immediately useful library that gained a number of enthusiastic users.

In switching to RSpec, I had to given up invariants (sigh). But in turn something wonderful and unexpected happened. The interaction between the Given/When/Then declarations and the nesting of the describe and context blocks turned out to be a beautiful thing. I found myself investing on some setup at the top of a file, and then each test case was a study in the minimal amount of difference between the scenarios and the "standard" setup. Suddenly specs were beautiful and expressive.