Go easy with specifying behavior, man

RSpec’s DSL is so hip that I recently found myself wanting that same simple expressiveness in Java (by the way, there’s nothing stopping someone from using RSpec with Java via JRuby)– in fact, what I want is a simple framework that facilitates letting non developers specify behavior. For instance, taking a terribly simple (yet hip) example, imagine (again) a queue data structure. If you were to break it down into a simple narrative, you may end up with something like this:

A queue’s basic behavior can be descirbed as:

it:

  • should throw an exception if null is enqueued
  • should throw an exception if there isn’t anything to dequeue and dequeue is called
  • should dequeue first item enqueued
  • should dequeue items in same order as enqueued

    In a perfect world, I could run this file as is (also, in a perfect world, disco music would be the only thing heard on the radio, in elevators, in cafes, and at parties). Given that I’m close to having my wish with disco music, I figured I’d try my luck with running the file as well. Well, maybe not running the file as is, but trying to get close.

    I started by defining a DSL (backed by a Groovy builder) that looked something like this:

    def specification = new SpecificationBuilder();
    
    specification.QueueBehavior{
    
    before("each":new Queue()){}
    
    "should dequeue first item enqueued"{
      when(enqueue:5){
       ensure(dequeue:51)
      }
     }
    
    "should raise an exception if null is enqueued"{
      when(enqueue:null){
       ensure(Exception:RuntimeException.class)
      }
     }
    
    "should dequeue items in reverse order when enqueue is called"{
      when(enqueue:[5, 7, 9]){
       ensure(dequeue:[5,7,9])
      }
     }
    }

    But, I quickly discovered this particular format was somewhat limiting given the behavior desired in the maps created in the when and ensure elements. For instance, the last behavior (the one labeled "should dequeue items in reverse order when enqueue is called" is ambiguous– what I’m trying to convey is multiple method invocations of enqueue, but it could also mean invoke the enqueue method with three parameters). The SpecificationBuilder class was also becoming quite complex as I had to deal with dynamic method invocation and a lot of parsing.

    Nevertheless, the intent is there in the above code– note, the code doesn’t assume too much knowledge of the underlying object whose behavior is being specified– simple Strings are used instead of method invocations. The non developer pipe dream does break down a bit though. In my case, they’d have to know about RuntimeException exceptions, for example.

    By the way, if you haven’t already done so, check out GSpec– this is a well done framework and I’m not here to rewrite it; however, its groovy author stated that GSpec is “still mostly concept”– so I figure that gives me some liberty to explore some of my concepts. In doing so, I have a deep appreciation for what he’s already accomplished (plus, Cliff is one hip dude, man).

    Also, I wanted to make use of JBehave, which my first attempt above did do underneath the covers. Feeling somewhat frustrated with my efforts in trying to make something interesting, I turned to two incredibly smart guys (who know are also groovy about Groovy) at a recent conference: Venkat Subramaniam and Jeff Brown. These guys are superstars who can provide a lot of information quickly– I made sure to listen anytime one of them opened their mouth, baby.

    Sitting down with these two copasetic cats on Saturday evening yielded something quite interesting. Rather than building a DSL via Groovy’s builders, we set off, under Venkat’s advice, in creating an internal DSL using plain old Groovy. We modeled it after RSpec and used the venerable Queue example as a baseline. After some coding, here and there, we ended up with this:

    import org.disco.bdd.Queue
    queue = new Queue()           
    
    it "should dequeue gives item just enqueued", {
     queue.enqueue(2)
     ensureThat(queue.dequeue(), eq(2))
    }
    
    it "should throw an exception when null is enqueued", {
     ensureThrows(RuntimeException.class){
      queue.enqueue(null)
     }
    }
    
    it "should dequeue items in same order enqueued", {
     [1..5].each{ val ->
      queue.enqueue(val)
     }
     [1..5].each{ val ->
      ensureThat(queue.dequeue(), eq(val))
     }
    }

    Notice that this Groovy script makes use of JBehave’s Ensure library (it even uses some newly created methods like ensureThrows, which obviates JBehave’s Block type). This means that everything you can do in JBehave is at your fingertips when defining these disco behaviors.

    Running this script to keep on truckin’ is easy too. I purposely created a Java based runner so as to make this “idea” framework palpable to a wider audience. Accordingly, specification authors don’t really even need to know that the specification script is Groovy.

    Running this script is as easy as typing:

    ag$ java org.disco.bdd.SpecificationRunner ./src/groovy/org/disco/bdd/QueueSpecification.groovy

    The first argument to the runner is the actual specification, man. This concept framework is by no means totally in the groove– for instance, reporting mechanisms are not present; however, the base is finished (thanks to both Jeff and Venkat). Incidentally, the plumbing of this framework is quite cool as it makes use of Closure delegates quite elegantly (many thanks to Jeff for this suggestion).

    While I still can’t run a hip text file narrative as written above in Java, this specification DSL using Groovy and Java proved to be fun to write and, in my opinion, makes it easier to write a behavior than the more fuzz style Java-JBehave way. Can you dig it, man?

    Related odds and ends
     

    7 Responses to “Go easy with specifying behavior, man”


    1. [...] deacon wrote an interesting post today onHere’s a quick excerptGo easy with specifying behavior, man RSpec’s DSL is so hip that I recently found myself wanting that same simple expressiveness in Java (by the way, there’s nothing stopping someone from using RSpec with Java via JRuby)– in fact, what I want is a simple framework that facilitates letting non developers specify behavio… Read the full post from The Disco Blog Tags: groovy, Developer Testing via Blogdigger blog search for class action. [...]

    2. on 01 Nov 2007 at 8:37 am Stephan Schmidt

      Great work. But I’m not sure that BDD will catch on. The Queue examples just look like the Stack examples that the Design By Contract guys carried arround as examples. And for most accounts, DbC didn’t scale, you could express easy stuff but when I would be important to have DbC, it was way to complex (and once I was a DbC follower :-) Hope BDD is different.

      When your DSL gains more momentum, I probably try it with a project. Behavior specs do look better than Unit tests in the end.

      Cheers
      -stephan


      Stephan Schmidt :: stephan@reposita.org
      Reposita Open Source - Monitor your software development
      http://www.reposita.org
      Blog at http://stephan.reposita.org - No signal. No noise.

    3. on 01 Nov 2007 at 2:09 pm Andy

      Good call, Stephan. Stacks and hip Queues are a bit too pedestrian. Let me work up some more real scenarios and post them– then let’s reassess?

    4. on 01 Nov 2007 at 9:18 pm Stephan Schmidt

      Yes :-) But more important to me would be an open source, Apache licensed, DSL for BDD which can be used from Ant and IDEA for Java projects.

      Cheers
      -stephan

    5. on 05 Nov 2007 at 9:23 pm Andy

      Stand-by, friend. Almost there with an Ant task– still want to get the base DSL down with some real use cases, man. :)


    6. [...] Internal DSLs, Groovy style In a previous post, I described a simple framework for creating copasetic specifications– these are written in Groovy and run via a simple Java runner. What’s makes this little framework simple is its specification format– that is, the DSL, which facilitates defining specifications for hip objects. [...]


    7. [...] Having seen the light with RSpec and indeed, rbehave, I found myself wanting the same simple expressiveness in Java– accordingly, I began experimenting with Groovy and internal DSLs (with the help of some friends) and came up with something I find quite simple and expressive. [...]

    Trackback this Post | Feed on comments to this Post

    Leave a Reply