Groovy DSL fun again!


So I’m writing these ad-hoc Groovy scripts to update a chart on an internal wiki page when I start feeling the urge to play with the syntax. Groovy is so much fun to use that you just can’t help but mangle with things once you get the hang of it. Hi, I’m Cliff. You’re here because you like to alter the rules of your programming language while it’s running.

It’s been some years since I fooled with GSpec and all the meta-programming stuff. So now I start my latest script (half into the project) and decide to express what I want the script to work like before I write the code. It’s a fairly straight forward task and I find it very easy to bend Groovy syntax to say exactly what I’m thinking while remaining executable. So I start with this:

def whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString){
    return "I'm not converted yet! :("
}

def then(action) { action() }

def givenJson = '''
{"my-latest.apk":
    {"totalSizeFormatted":"14.84 MB","imagesSizeFormatted":"6.22 MB",
    "textSizeFormatted":"426.37 KB",
    "resourcesSizeFormatted":"2.04 MB","executableSizeFormatted":"1.15 MB","audioFilesSizeFormatted":"376.10 KB",
    "totalSize":15562499,"imagesSize":6517513,"textSize":436603,
    "resourcesSize":2141448,"executableSize":1202497,"audioFilesSize":385126},
}'''

def andGivenTableMarkup = '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 |
'''

def andGivenApkVersionString = '2.8.0.25'

def result = whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString)
then {
    assert result == '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 | 2.8.0.25 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 | 1174.31 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 | 2091.26 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 | 6364.76 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 | 426.37 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 46.09 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 | 15197.75 |
'''
}

Then taken some learning from my recent Python training I thought, “Hey, why not include this test as an expectations string at the bottom of my script, similar to how Python uses doc-strings!”

def expectations = """
def whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString){
    return "I'm not converted yet! :("
}

def then(action) { action() }

def givenJson = '''
{"my-latest.apk":
    {"totalSizeFormatted":"14.84 MB","imagesSizeFormatted":"6.22 MB",
    "textSizeFormatted":"426.37 KB",
    "resourcesSizeFormatted":"2.04 MB","executableSizeFormatted":"1.15 MB","audioFilesSizeFormatted":"376.10 KB",
    "totalSize":15562499,"imagesSize":6517513,"textSize":436603,
    "resourcesSize":2141448,"executableSize":1202497,"audioFilesSize":385126},
}'''

def andGivenTableMarkup = '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 |
'''

def andGivenApkVersionString = '2.8.0.25'

def result = whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString)
then {
    assert result == '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 | 2.8.0.25 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 | 1174.31 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 | 2091.26 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 | 6364.76 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 | 426.37 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 46.09 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 | 15197.75 |
'''
}
"""

println expectations

Taking it a step further I can pass the expectation string to an eval call (or whatever the Groovy “eval” equivalent is, I’ve been mixing my scripting languages a lot these days…) and execute the test while passing the current object into the evaluated context. I can do all of this without frameworks or anything fancy. If I sprinkled just a little meta-programming into the mix then I could remove the definitions for the “then” and the “whenWeConvertItToTableMarkup” methods and have it read like a real spec!

Using Groovy to test your Groovy assertions over Groovy code examples


…Because I just can’t think of a better title for an article that is so self describing. Hats off to Ted Naleid, I’ll definitely be paying return visits to his site. Many people won’t appreciate the sheer awesomeness of the idea Ted describes. Let me see if I can explain through colorful analogy. Say you’re making a garden. Go ahead, say it… and say it loud enough for a co-worker or passerby turn attention or raised eyebrow in your general direction. Now why would you, an accomplished software designer or general director of technology or whatever your current IT status happens to be (I know you work in IT or else you wouldn’t be reading), why would you suddenly take up gardening in the middle of the work day? Simple! You’re eager to figure out where my idiotic rambling is going to take you. At any rate, I’ll stop embarrassing you long enough to arrive at some sort of tangible conclusion. But before I get back on track, say you’re also a fan of Martha Stewart. Say it out loud as you did earlier and hold your hand in a dainty position slightly bent at the wrist with a pinky extended outward causing even more attention to be directed toward your cubicle. (That’s not as relevant but it sure makes for an interesting exercise in blog reading and I’d love to hear your results at the end of my contorted writing.)

Now as a gardener, fan of Martha, you wish to grow cabbage, tomatoes, and turnip. Pretend now, if you will, that you can use the very tomatoes you grow in your garden to grow the turnip. Pretend further that the turnip could be used to grow the cabbage. Now let’s say that the cabbage is what we used initially to grow the turnip! What we’ve managed to do is create our own self feeding self nourishing garden! Wouldn’t Martha be proud? Now before you contact Mrs. Stewart for air time and/or collaborative television time in our make believe world let’s come up with a name for our phenomenon. Recycled gardening? Veggie Groomed Veggies? Organically grown organics grown from organics grown organically (…from other organ… you get the point, right)? Recursive Horticulture? Got your name picked? Make note of it for the comment section.

Terrible analogies aside, the same idea expressed in our gardening adventure is what Mr. Ted outlined on his blog. He just didn’t get all apron and potted plant about it. Anytime you can use code you’ve written to describe the very code you’ve just written then you’ve done, as Bush says to Brown, “A heck of a job!” Anytime you can use that very same self-describing code to validate the code itself then you’ve done your country an honorable service. Then when you graduate to the next level and use these very same programming exercises to extract your self-describing self-validating examples from the text of an article used to display how John Blaze you are… I dunno… there’s no words, analogies, or urban slang capable of painting such a picture of finesse. Well done Mr. Naleid! Well done…

To find out what the above madness is all about click here and read on. It’s an article on using the Groovy programming language to extract from and article and execute mini Groovy programming examples that also double as mini one line unit tests proving to both the reader and author that the programming logic is correct.

Groovy Ant Secrets


I was pondering about this earlier today. Wondering how I would invoke an Ant task that used nested text data using Groovy Ant. Why? Because I looked at the Ant script task while browsing Ant docs and said, “Hmm. that’d be neat to embed a script in a GroovyAnt build… but how do I pass text?” Well it just dawned on me that the random errors I’d been getting with Groovy’s AntBuilder exposed the answer. Occasionally I’ll forget to prefix a task attribute with an attribute name like:
ant.available(property:'menu.icon.found', '/menu.png', classpath:'target/MapQuestCoolStuff.jar')
And I’ll get an error saying:
ERR: SCRIPT FAILED: The type doesn't support nested text data ("/menu.png").
ERR: The type doesn't support nested text data ("/menu.png").

It’s telling me that the second parameter is being passed to AntBuilder as text instead of a task attribute.