How Clojure improved my Groovy

January 15, 2010 7 comments

Dave Thomas and Andy Hunt have been saying for years that you should learn new programming languages. Doing so improves your skill in any language, whether you use the new language or not. I believed this with some skepticism, but decided nonetheless to start learning Clojure after reading The Pragmatic Programmer.

I’m reading and working through Programming Clojure, and one of the examples in the book looked like this:

(use '[clojure.contrib.str-utils :only (str-join)])
(str-join "-" ["hello", "clojure"])

Then, a week or so later, as I was working on some Groovy code, I saw something like the following:

def elements = ["It", "works", "on", "my", "machine!"]

def sb = new StringBuilder()
elements.eachWithIndex { element, index ->
  if (index == 0) {
    sb.append(element)
  } else {
    sb.append(" ")
    sb.append(element)
  }
}

assert sb.toString() == "It works on my machine!"

And I thought, “man, this code would be so much better in Clojure!” Since I can’t use Clojure for my job (yet), I set out to find a better way to do this in Groovy. I decided to look for something similar to Clojure’s str-join for Groovy, and I found the join() method. It does exactly what I needed!

def elements = ["It", "works", "on", "my", "machine!"]

def sb = new StringBuilder()
sb.append(elements.join(" "))

assert sb.toString() == "It works on my machine!"

And so, I discovered for myself that Dave and Andy were right. Knowing Clojure (specifically, the clojure-contrib library) helped me to write better Groovy code.

SnakeYAML and Groovy

January 13, 2010 5 comments

I had some fun playing with SnakeYAML and Groovy the other day. Below are some of my results. If you want to run this in your groovyConsole, you need to download SnakeYAML and add the snakeyaml-<version>.jar to your classpath.

From YAML to Groovy:

import org.yaml.snakeyaml.Yaml

Yaml yaml = new Yaml()
def obj = yaml.load("""
a: 1
b: 2
c:
  - aaa
  - bbb""")

assert obj.a == 1
assert obj.b == 2
assert obj.c == ["aaa", "bbb"]

From Groovy to YAML:

import org.yaml.snakeyaml.Yaml

def map = [name: "Pushkin", aliases: ['P', 'Push']]
Yaml yaml = new Yaml()
String output = yaml.dump(map)

assert output ==
'''name: Pushkin
aliases: [P, Push]
'''

Isn’t YAML so much simpler and cleaner than XML? Why aren’t more of us using YAML with Java and Groovy?

Top 5 posts of 2009

December 31, 2009 Leave a comment

Upgrading Maven from 2.0.x to 2.1.x – profiles.xml

October 26, 2009 Leave a comment

When we tried to upgrade from Maven 2.0.x to 2.1.x, our build broke, indicating we had a problem with our profiles.xml. I had a hard time finding out what’s supposed to be in the profiles.xml, since I couldn’t find a reference to the schema on the Maven website.  I finally found a profiles.xml in one of our projects at work that referenced the profiles XML schema, which can be found here:

http://maven.apache.org/xsd/profiles-1.0.0.xsd

I’m still not sure if the schema changed from 2.0.x to 2.1.x, but I know that using <profiles/> as the root element worked in 2.0.x but did not work in 2.1.x.  When you upgrade to 2.1.x, make sure the root element in your profiles.xml is <profilesXml/>. Actually, you can make the change to your profiles.xml before upgrading to Maven 2.1.x and then upgrade when you’re ready.

Tags:

Mocking and stubbing in Groovy with ‘with’

October 5, 2009 1 comment

I often use metaClass in Groovy to create mocks or stubs in my unit tests. Recently I’ve discovered that the with method makes this a bit simpler.

This:

Foo.metaClass.with {
  doSomething = {
    return true
  }
  anotherThing = {foo ->
    assertEquals 42, foo
  }
}

is slightly shorter than this:

Foo.metaClass.doSomething = {
  return true
}
Foo.metaClass.anotherThing = {foo ->
  assertEquals 42, foo
}

and less code means less bugs.

[Update: For more explanation of why the with method is so great, read this post.]
[Update: And for another way to write your mocks and stubs, see my previous post on mocking with Groovy.]

Integrating Unit Tests

August 19, 2009 Leave a comment

There’s been a lot of talk about TDD, Responsibility Driven Design, and what constitutes a unit test versus an integration test this week at work.  It got me thinking about the definitions.  I used to think it was very clear cut. Unit tests isolate a single class, integration test don’t.

Is the line so simple though?  What about a unit test that tests a method that uses other methods within the same class to get its work done.  Is testing the results of that method a unit test?

For example:

// Say I wanted to test the method.
String makeDeposit( String xmlData ) {
def transaction = parseRequestXml( request )
def receipt = bankBusinessObject.deposit( transaction )
return makeResponseXml( receipt )
}

To be a unit test, I should at least mock the bankBusinessObject, and should probably ask the Mock to fail my test if the deposit method isn’t called.

But, it seems that to be a true unit test for makeDeposit, I should also mock parseRequestXml and makeResponseXml. And, for the makeDeposit unit test, rather than test that you get the expected xml repsponse data given the controlled input data, just ensure that makeDeposit calls parseRequestXml to parse it, bankBuisinessObject.deposit to act on it, and makeResponseXml to marshal the results.

I did some brain storming and came up with a new classification scheme for organizing my tests.

Unit

  • Macro Unit Tests – Tests isolated to a single class.  This is where you’d see testing of methods which call other methods to get some of their work done.
  • Micro Unit Tests – Tests isolated to a single method.  Completely test the method in isolation, mocking as necessary.   If you work in a language like Groovy and want to unit test a method that calls or depends on other methods in the same class, mock the dependent methods individually and have the mocks fail the test if they’re not called as expected, in the order expected.  I’m not sure if that is possible in Java.  (Maybe with some sort of test harness with AOP involved to intercept the method calls during the test??)

Integration

  • Standard Integration Tests – Integration tests that span other methods, classes, depend on other services, databases, etc.
  • Requirements Tests – Tests for those when you want to test a specific requirement or bug fix.  Very helpful when something changes later that breaks the bug you fixed a few releases back.  Or when the customer opens a ticket asking for functionality that contradicts a previous request.

Thoughts?

Java 6 and Maven on Mac OS X Leopard

August 12, 2009 3 comments

This morning I was having problems with Java and Maven on my Mac. I had my JAVA_HOME set to /Library/Java/Home, which was pointing to Java 6. When I ran mvn -v, Maven told me it was pointing to Java 5. I couldn’t figure out what was wrong because running java -version showed me Java 6.

The solution, which I found in this post, was to set my JAVA_HOME to the actual place where Java is installed, which is something like:

/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home

This worked for me, but YMMV.

Tags: , ,
Follow

Get every new post delivered to your Inbox.