Syntactic Saccharin

As I learn a language I’m always a bit leery of apparent syntactic sugar. Consider the following snippet of CoffeeScript:

if typeof num is not 'number'
  console.log 'not number'
if typeof num not 'number'
  console.log 'not number'
if typeof num != 'number'
  console.log 'not number'   
unless typeof num is 'number'
  console.log 'not number'

Reading them, they could, depending on the implementation, all be semantically the same: show the message if the variable isn’t a number. However if you’re familiar with CoffeeScript you’ll know that this isn’t the case at all. CoffeeScript generates JavaScript, so lets see what you get for JavaScript…

if (typeof num === !'number') {
  console.log('not number');
}
if (typeof num(!'number')) {
  console.log('not number');
}
if (typeof num !== 'number') {
  console.log('not number');
}
if (typeof num !== 'number') {
  console.log('not number');
}

Ok, so not is a unary operator, and the first two don’t work out at all. The last two, are equivalent, so unless is syntactic sugar.
Ruby offers, if ... else, if modifier, unless ... else , and unless modifier, so you end up with:

if x == 1 then
    puts 'hi'
end
puts 'hi' if x == 1
unless not x == 0 then
    puts 'hi'
end
puts 'hi' unless not x == 0

That just seems a bit nuts. Certainly some are more or less expressive in different circumstances but I feel it’s more minutia to keep in mind. You need clarity and correctness in your code and when I’m dancing across several peoples code styles in several languages, the slight expressiveness boost, at the cost of ambiguity, just doesn’t feel like a win.

Some of the issue is in the language cultures however. When is the last time you saw a do { ... } while condition in Java? It’s there but never used.

If I didn’t think I would annoy most everyone, I’d have static code analysis complain about the use of unless and the if/unless modifier syntax.

T. E. Lawrence

At a young age (i.e. long time ago) I saw the movie Lawrence of Arabia and was fascinated by the man and the story. Over the years I’ve watched the movie many more times, and read all I could by T. E. Lawrence and about him.

What is it about him that pulls me in? I think it’s a combination of admiration for him as a person, but also a deep sadness at how misguided the motives were, of those he opposed, and his own.

If you’re not familiar with his story, he was an intellectual man, a misfit in his society, that through his service as a British army officer became embroiled in Arab/European politics in World War I. He played a influential role in Arab independence movements to try to avoid colonial powers simply dividing up the region.

At first glance, and certainly what the movie feeds on, he can be seen as an amazing individual. One man walking into oppressive chaos, and trying with some success, to shape a form of order, against the colonial powers. Even in that surface interpretation it is bitter sweet because he ends up marginalized and much of the changes he strove for evaporate.

But looking deeper the events have more significance. While he was driven by respect for the Arabs, and their culture, he was still trying to bring them a very European humanitarian solution to the European problem, in an Arab world. He was trying to fight the colonialists by making the Arabs their peer. Getting them to join them, rather then be beaten by them. His intentions were good, his commitment and achievements amazing, but it was misguided and ethnocentric, and doomed to fail.

He was a truly amazing man,  instrumental in some epic adventures, and a prolific writer, so there is a lot of (obviously biased) material available.

It the end of the day, for me, his failings are perhaps more of interest then his successes. And trying to sort out the impact, if any, good and bad, and it’s legacy is challenging.

AssertJ, Stands On Its Own

Smell The Clutter

Java, with a healthy dose of testing code, has been my mainstay off and on for many years now.  JUnit and assertions have been a big part of my goto tools for most of that.  JUnit’s assertions felt underpowered from the start so, like most folks, I jumped on frameworks like hamcrest and fest. In some of code that’s old, or had a lot of hands in it, the result is a bit of a confused mess of all the possible frameworks.  Messy tests is as bad a code smell as any. Hamcrest hasn’t seen changes in ages and it appears fest is now abandon-ware so I decided it was time to deal with the smell.

Fest had been my preferred assertion framework and so AssertJ, the fest descendant with a still active community, was an obvious choice.  Some initial test usages proved it to be a cleaner fest. And so I began refactoring tests to use only AssertJ, removing JUnit’s, fest’s and hamcrest’s assertions.

Using AssertJ

AssertJ has a nice clean approach to assertions. It uses a factory method Assertions.assertThat() to create a type specific assertion. The type specific assertions offer fluent interfaces that are largely polymorphic.

Simple Example

static import org.assertj.core.api.Assertions.*;
...
@Test
public void shouldProvideAnExample() {
    String actual = "This is a test";
    assertThat(actual).contains("is");
    String[] actualArray = new String[]
               {"This", "is", "a", "test"};
    assertThat(actualArray).contains("is");
}

In the example above, assertThat() creates the appropriate type of assertion (String, Array) and contains, on a string looks in the string, and on the array searches the array.

Fluent API

One of AssertJ’s feature I like is its fluent API. In particular it’s cleaner than hamcrest’s approach IMHO. Consider, for example, determining if a string is between two values. There is a isBetween, but even barring that, the fluent approach looks like:

     assertThat(actual).isGreaterThan("bbb")
                         .isLessThan("ccc");

Where as hamcrest this would read (if there was greaterThan and lessThan):

     assertThat(actual, 
                 allOf(greaterThan("bbb"), 
                       lessThan("ccc")));

Clearly the two approaches are equally expressive, but I find the fluent syntax easier to scan.

Custom Conditions

import org.assertj.assertions.core.Condition;
static import org.assertj.core.api.Assertions.*;
...
@Test 
public void shouldBeEvenlyDivisibleBySix() { 
    Condition<Integer> evenDivBySix = new Condition<Integer>() { 
        @Override 
        public boolean matches(Integer value) { 
            return (value % 6) == 0; 
        } 
    }; 
    assertThat(12).is(evenDivBySix); 
    assertThat(8).isNot(evenDivBySix); 
}

In this example a condition was created that determined if an integer is evenly divisible by six and then used in assertions on integers.

Custom Assertions

Sometimes you’ve your own types with corresponding common assertions you’d like to apply to them. Perhaps you want to know if a Student instance isInMiddleSchool?
I won’t walk through all the interface implementations here, but the process is quite straight forward.

  1. Subclass AbstractAssert for Student and implement a isInMiddleSchool.
  2. Subclass Assertions adding a new assertThat factory method for your StudentAssert you created.
  3. Use your new factory and assertions as you’d always (i.e. assertThat(student).isInMiddleSchool())

That simple.

The Refactoring

The transition from fest was basically changing some imports and a few small tweaks (see Assertj Migrating from Fest).  JUnit’s assertions were largely an import change and a simple regex or two. Hamcrest was a bit uglier…. and more satisfying.

What Didn’t Work Out?

Everything worked out except a few glitches around Hamcrest.

  • Hamcrest has native bean support via getProperty that AssertJ doesn’t offer. Coded around those using AssertJ’s Conditions.  Probably could have found another Bean/POJO accessor class but was trying to reduce frameworks.
  • At least one mocking framework depends on Hamcrest for some features.  The dependence was minimal and didn’t introduce much clutter into the tests.

Slides Based on This Post