GSpec revisited


I’m playing with GSpec some more because I can’t keep my mind off of it. There’s something about programming in what practically reads like english that amazes me. Being able to do that with a language that I created, a language that compiles to JVM byte-code, a language that runs on my JVM, is just awesome! (That’s right! I’m stealing all of the credit from the RSpec team! It was MY idea dangit! They stole it from me and I deserve full credit!) Here’s what I got so far:

class Stack {
   boolean isEmpty() { data.size==0 }
   def data = []
   def push(def val) { data << val }
   def pop() { return data.pop() }
   def peek() { return data.pop() }
}

class GSpecDelegate  {
        public object

     GSpecDelegate(obj) {
       object = obj
     }

	def wrapObj(obj) { return new GSpecDelegate(obj) }

        def getProperty(String name) {
                if (name.startsWith('should_be_')) {
		  def predicate = name.substring(10)
                  def prop = object."${predicate}"
                  assert true == prop : "Should be ${predicate}"
                  return wrapObj(prop)
            } else if (name.startsWith('should_not_be_')) {
		  def predicate = name.substring(14)
                  def prop = object."${predicate}"
                  assert true != prop : "Should NOT be ${predicate}"
                  return wrapObj(prop)
                } else {
                  return wrapObj(object."$name")
            }
        }

        void setProperty(String name, value) {
                object."$name" = value
        }
       
        def invokeMethod(String name, args) {
            if (name.startsWith('should_equal')) {
                   assert object.equals(args[0]) : "Is not equal. Expected [${args[0]}] while the actual is [${object}]"
            }
            else if (name.startsWith('should_not_equal')) {
                   assert false==object.equals(args[0]) : "Is unexpectedly equal. Expected a value different from [${object}]"
            } 
            else return wrapObj(object."$name"(*args))
        }
}

class GSpecBuilder {
   def objects = [:]
   def currentContext
   def currentSpec

   def invokeMethod(String name, args) {
        def closure = null
        switch(name) {
                case "context":
		    currentContext = args[0]
                    println currentContext
                    closure = args[1]
                        break
                case "setup":
                        closure = args[0]
                        break
                case "specify":
			currentSpec = args[0]
                        println "\t" << currentSpec
                        closure = args[1]
                        break
        }
        if (closure!=null) {
                closure.delegate = this
                closure.call()
        }
   }

   def getProperty(String name) {
    objects.name
   }

   void setProperty(String name, value) {
    objects.name = new GSpecDelegate(value)
   }
}

def the = new GSpecBuilder()
the.
  context('A new stack') {
     setup() {
        the.stack = new Stack()
     }
     specify('Should be empty') {
        stack.should_be_empty
     }
     specify('Should NOT be empty after a push') {
        stack.push "value"
        stack.should_not_be_empty
     }
     specify('Pop should return a value pushed') {
        stack.push "value"
        stack.pop().should_equal "value" 
     }
     specify('Peek should return a value pushed') {
        stack.push "value"
        stack.peek().should_equal "value" 
     }
  } 
the.context('A stack with stuff in it') {
     setup() {
        the.stack = new Stack()
        the.stack.push "value"
     }
     specify('Repeat peeks should return the same value') {
        stack.peek().should_equal "value" 
        stack.peek().should_equal "value" 
     }
}

Copy and past all of the above into your groovyConsole and hit Ctrl+R. It’s really slick. Of course you would want to hide the GSpec implementation classes from the actual spec you were writing but this is cutting edge stuff so bear with me a moment. I’m blown away by the implementation. The fact that I, a novice groovy programmer, was able to implement this much in such a short time is off the hook! (That’s right! I’m stealing credit from one of the lead Groovy developers, Blackdrag. He had nothing to do with the above text. If you browsed any replies on the Groovy mailing list I assure you the entire code base came initially from me in an off list emailing!)

Ok, so it isn’t all my hard work. It’s all good anyhow since we’re all on the same team right? Anyhow, it was my idea originally. Well, it kinda was. I mean I didn’t come up with the idea of executable specs but I decided to do it in Groovy. Who cares who’s idea it was! The stuff is bonkers. I’m going to keep tweaking it until I can shoehorn it into our production codebase as a JUnit alternative.

4 thoughts on “GSpec revisited

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s