Friday, January 29, 2016

Intentional Unit Testing

Do your unit tests easily reveal their intention?  Can I look at the test method and easily reason why the assert should be correct?
Sometimes, in our quest to remove duplicate code and to use test fixtures and data builders we obscure the data in our test objects.  If I need to navigate through builders and set-up methods to understand how the test works - I’ve reduced the test’s value.
Intentional tests combine the set-up, test execution and assertion in a logical manner so I can immediately understand what is being tested and why the test should pass.
In this first example I test a Story object’s ability to return all the hobbit characters.  I use a test fixture for a list of characters.  But, why are these these the hobbits we are looking for?  We could make this test more intentional.


This example simply creates the list in the test method.  This helps me reason about the test and easily understand why the expected result is correct.  I still use some test fixtures by way of the character instances.  But because these are well known characters I can leave out some of the details.


The final example shows that if we all understand who is in the group of characters I can lean on the test fixture a bit more.  This is intentional because everyone on the team knows who is in the Fellowship of the Ring.


Intentional testing was explained to me by Korey E.
Thanks to AssertJ for their awesome assertions.

Tuesday, June 23, 2015

Negative logic, it's not great

Early in my programming efforts I learned that negative logic can and should be avoided.  Many developers don’t think twice about introducing negative constructs into a class - I think that is a mistake.

I'm going to use the following code snippet as an example.  It is from a well known open source project.  The goal of the method is to return a list of classes in a given class' hierarchy, excluding the Object class. It has an interesting negative condition that drives a while statement - I think it can be improved.

I believe negative logic suffers from the following issues:

  • Difficult to read / conceptualize.
    The while statement is difficult to understand Object.class is not equal to cls and it is not null?
  • Negative symbols are easily missed. Java's negation symbol of ! is easy to overlook - especially when used at the start of the condition: !Object.class.equals(cls);
  • Difficult to combine negative conditions. For example what is wrong with this condition (x != 1 || x !=3)? You need to swap “or” (||) for “and” (&&). This is a very common programming error, all values are not equal to 1 or 3.
  • Expands the number of test cases needed to verify correctness. There are many classes that are not equal to Object.class, only one that is equal.
Refactoring this condition to positive improves the readability.  Extracting the condition to a method allows me to give it a name.

There are cases were negative logic works better because it can be less verbose and concise.  However, take some time to evaluate your negative conditions and see if they can be refactored to positive.

Saturday, November 1, 2014

Your Great Code

Great code does not come from code reviews, code quality reports, using the latest tool or programming language.  Great code is built by developers who care about their work…

Where does this passion for code come from?  It comes from within.  Somewhere in your past this attitude or culture was impressed upon you. It makes up your value system, your personal philosophy.   

My journey began working on my first car with my Dad.  My feeble attempts to tape and rig my car into working order didn’t work.  Most of my repair attempts just made things worse.  Dad impressed on me two lessons;


  • If something is worth doing, it is worth doing right
  • Finding the correct way to fix a problem is always the best solution

We purchased a shop manual for the car and made regular trips to junk yards. Understanding the mechanics of the car and obtaining the correct parts made a big difference in my repairs.


I attended a small liberal arts college in Rome, GA - Berry College. All students were encouraged to work on campus.  My job was helping our stonemason in the repair and caring of the stone walkways and walls that made up parts of the campus.  I mixed concrete and hauled stones.

I learned to mix concrete and select the right stones for a repair. I also discovered that helping getting the correct slope on a walk way so rain doesn't pool imparted a degree of satisfaction. I learned the value of work done well.

Berry has a student code, during my college days it seemed like a relic from the past.  Time has helped me understand its wisdom.


"I promise not to be content with slip-shod or merely passable work.  I will take an interest in all my work and learn to do the right thing in the right way".
- The Berry Code circa 1920

How did you learn to care about your code?

   

Friday, August 15, 2014

Java 8 Mixin

Java 8 introduced default interface methods. These allow an interface to provide a "default" implementation of a given method.  The default methods are used in Java 8 to add new behaviors to collections (mostly around streams) without breaking existing implementations.

Default methods also open Java to the type of language construct known as a mixin (ruby) or trait (scala).  This blog post illustrates using default methods to add comparison behavior in a class.

Problem to solve...

Java has a cumbersome API used to compare objects.  The compareTo method returns an integer whose value and sign defines if the objects are less than, equal to or greater than each other.  I want to improve this by defining a interface that has default implementations of isLessThan, isGreaterThan and isEqualTo mixin methods.  I want to be able to simply take a class that already implements Comparable and change the interface it implements to one with these new default methods. 

To demonstrate this concept I'm going to use a Zombie domain class.  The type of  a zombie defines how it compares to other zombies.  The hierarchy is as follows: Walkers are less than Runners, which are less than Fatties, which are less than Abominations (nod to Zombicide).

This first version of the Zombie class implements the Comparable interface and implements the corresponding compareTo method.  The test for the class ensures the compareTo method works based on the integer and sign returned from the method.


Solution...

This test illustrates the issue I want to fix.  To determine if one zombie is bigger than another I need to check the returned value.  This makes the code difficult to read especially for developers not familiar with the compareTo function.  It is not a fluent API.  I can improve this using an interface with some default methods.

This interface will add the methods I am looking for to my Zombie class - it could add these methods to any class that already implements Comparable. The technique used here is that I am referencing a method that the class already has - compareTo, and expanding how it can be used.

The final listing shows that Zombie now implements Compares, and no additional changes.  The tests now use the new isLessThan, isGreaterThan and isEqualTo default methods.

Wrap-up

Default methods add another technique you can use to mange cross cutting behaviors in your classes.  At first glance they seem to be a hack used by the API designers to extend the old Java APIs.  I think they are solid addition to the language.

Sunday, May 11, 2014

Agile - where to start?

Understanding Culture
If you ask me about the culture of running I shouldn’t start by telling you to do long slow runs on Sundays. While long runs are part of the story they are simply a practice. No, I need to give you some context by describing the values or principles of running. Maybe the idea that runners (vs. joggers) value running as a sport - beyond just fitness. Runners come in all speeds but they push themselves to improve - which is a principle. Doing longer runs is a training practice that can improve your ability. Traditionally, runners do long runs on Sunday but you can do them on other days.


You understand the culture based on the values and principles. The practices make sense within the larger context. You better understand why the long run is important. What if all your training runs are the same distance (you don't do long runs) are you really a runner? Well, if you believe in the values and follow the principles - then yes.



This idea can expressed as follows: Culture = Values + Principles (which are expressed through practices)



Understanding Agile Culture
I believe the same is true for understanding agile software development. Often we start by talking about stand-ups, stories, automated testing and all the other practices without setting the larger context. First you need to understand the culture (values and principles) before comprehending how they are expressed by practices.


Agile software development, as a culture, is defined by the Agile Manifesto. The four values and twelve practices define what and how we seek to achieve a goal. Missing these fundamental ideas leads to an incomplete understanding. Why not count "development complete" stories as progress? Because we value working code and believe that is the only measure of progress.


Start with understanding the agile values and principles
There is a lot of content about agile software development.  Lots of cool ideas, ways to communicate, retrospect, organize and enable successful projects - you can quickly lose your way and miss the big picture.


So, start your journey at the Agile Manifesto site and branch out from there. First learn the basics then understand how the practices fit together and enable the principles and values. Oh, and try to get in your long runs maybe a running partner (or pair?) that can help your focus and commitment.

Saturday, April 26, 2014

Hamcrest Matching with Lambdas

Using Hamcrest matchers within your JUnit tests is a great way to create understandable, fluent tests.  You can make this test matching special by creating your own matchers specific to the objects you are testing.

In this blog post I will show you how to author custom Hamcrest matchers.  I'll also show how lambdas can make these custom matchers simpler to code and a bit more expressive.

Set-up

I'm using Java 8 in my example.  You will also need to include the appropriate Junit and Hamcrest jars.  The normal Junit jars come with a small portion of the Hamcrest matchers included as a dependency.  I suggest using the Junit jar without Hamcrest and including the full core Hamcrest as a seperate dependency.

My build.gradle file, notice the junit and hamcrest dependencies.

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit-dep:4.+'
    testCompile 'org.hamcrest:hamcrest-core:1.+'
}

In my example we are killing zombies, my Zombie class is here.

Custom Hamcrest Matcher

There are a couple of abstract classes you can use from Hamcrest to build your custom matcher.  I'm using TypeSafeMatcher<T>, the generic is the class for which you are creating the matcher.  This method creates a custom matcher that asserts the type of zombie.

Hamcrest ensures your target object is the correct type and is not null.  The remaining methods to create are:
  1. protected boolean matchesSafely(Zombie zombie)
    This is where you do the actual matching to ensure the actual result matches expected.
  2. public void describeTo(Description description)
    These methods are used to build a failure message (see in red below).  This method creates the first line - "Expected: <description>"
  3. protected void describeMismatchSafely(Zombie zombie,    Description description
    This method creates the second line - "but: <description>"
java.lang.AssertionError: 
Expected: Zombie should be ABOMINATION
     but: was WALKER

Test Class using Custom Matcher

Custom Hamcrest Matcher using Lambdas

All good stuff and leads to expressive tests.  However, all the boiler-plate code around the custom matcher is tedious.  This is where lambdas can be used to simplify the custom matcher.

First: create a generic matcher that accepts lambdas.

This class is a template that can be used in multiple custom matchers.  It allows you to use lambda expressions in place of the custom matcher methods.

matchesSafely becomes a Predicate function
describeTo becomes a Consumer function
describeMismatchSafely becomes a BiConsumer (two argument consumer)

Using this class you can instantiate custom matchers with much less code.

Revised Zombie matcher using lambdas and the templates matcher class.

This class implements three custom Zombie matchers in the same space as the original version used to implement one custom matcher.


Monday, February 10, 2014

No Null Checks: Use Optional

I have a method that can return a null value.

Use the return type of Optional to let callers know they need to handle absent values.


In this example the null check is needed because the city code may not exist in the repository.

However, it is not clear from the findCity method that a null could be returned.  

When it is possible for a null to be returned from a method use an Optional wrapper class to let the caller know what to expect and that they need to handle the case where the value is absent.

The optional class contains the instance that can be null and offers several convenience methods to elegantly handle the null condition.  Java 8 users should use the java.util.Optional version - since it is integrated into the various Java 8 APIs.  For other users there is a version in the Google Guava framework. 

Refactoring the null check example results in the following new implementation.

By returning Optional from the findCity method we are explicitly letting callers know that we might not find the city based on the code. There are a lot of interesting methods you can use on Optional to deal with missing values - here are a couple to get you started.