DevOps Zone is brought to you in partnership with:

Jonathan Fullam is an Enterprise Content Management consultant with over 10 years of experience with software development. Currently employed by Micro Strategies, Jonathan designs and implements custom ECM solutions based on the Alfresco open source Enterprise Content Management platform. Jonathan will be speaking at The ServerSide Java Symposium in Las Vegas in March of 2011. Jonathan has posted 1 posts at DZone. View Full User Profile

Making Test Driven Development Work: Test Readability

02.23.2011
| 9053 views |
  • submit to reddit
To achieve an impeccable system design, write a failing test first, a simple implementation to pass the test, refactor and repeat. Sounds easy, right? Then why is it not so easy to get developers to adopt this technique on a regular, or better yet, permanent basis? One possible reason is because writing unit tests often becomes a burdensome task. Developers feel they have a better shot at meeting the always tight deadlines if they forego this mundane task. Even worse, the tests that do get written only seem to cause a nuisance, for when they break, it takes a considerable effort to decipher these unit pests and often chunks of code become commented out. This is because the act of TDD takes more than simply following those three steps. It takes a deeper understanding of why TDD improves the design of software. Specifically, how a developer approaches unit testing determines if TDD will work for them and their team.

A key characteristic of TDD that works is test readability. By focusing on test readability, a developer is forced to think about the object under test in a way that will promote good design and provide valuable documentation for the components of the system. This article provides a few quick tips to ensuring that a unit test clearly expresses an object’s intent that I initially realized after reading “Growing Object Oriented Software, Guided by Test” by Steve Freeman and Nat Pryce.

First, the name of a unit test name goes a long way to identifying the object’s purpose. Often times, a unit test is named by preceding an object’s method with “test.” This is troublesome for multiple reasons. First, the method should not exist yet if one is following the very important step of writing a failing test before writing any other line of code for that object. If the developer is predicting what that method name will be, they are also approaching the unit test in the wrong frame of mind. The developer should be thinking about the behavior of the object, the boundaries of that object, and how the object will be used. Thinking about a method name is thinking about how one will implement the object. This is a very important distinction when trying to benefit from TDD. Thinking about an object’s implementation when writing a test first is no different than actually writing the implementation first. Cohesion and readability are forced on the objects implementation when the developer is thinking about an object behavior first. Therefore, tests should be named precisely after the behavior they are testing. One technique created by Chris Stevenson, the author of a documentation generator for Java called TestDox, is to name the test methods as a sentence describing the objects behavior where the subject of the sentence is implicitly the object under test. For example, given a class that handles updating a documents workflow related properties when the document queue is changed (ProcessingInfoQueueNameChangeHandler)



It should be clear what behavior each of these methods is testing. More importantly, it should be clear as to what the object under tests does. It is important to note that it’s ok that these method names are quite long and you would never want to use such names in your production code. This is because these methods will never be explicitly called as Junit will use reflection to find and execute these methods. Another tip to improving the readability of your test code is to use Hamcrest matchers for your assertions. Hamcrest is a library of matcher objects used in various testing frameworks such as JUnit, TestNG, Mockito, and JMock. Test readability is improved with use of Hamcrest as it provides a more natural reading of the test assertions. In a nutshell, to use Hamcrest you use the following assertions:

assertThat([value], [matcher statement]);

For example:



Or



It is also important to note that it is easy to create your own custom matchers as well and this is recommended when you find multiple instances of the same conditional code in your assertions. Lastly, it should be clear what the literal values in your test code mean. It is difficult for someone to determine if the literal values you happen to use in your test are random or are important to the context of the test and its results. Therefore, it’s better to define literal values as constant variable where the variable names define precisely what is meant by the value. For example:



This is much more clear than if ANY_QUEUE_NAME was replaced by something like “Initial Review.”

Hopefully, these 3 tips will get you on the path to creating unit test that are readable. This will in turn put you in the correct frame of mind to yield the fruits of TDD and will provide your team with concise documentation for your objects. Ensuring that a unit test clearly states a behavior of an object is an important step to truly benefiting from TDD.
Published at DZone with permission of its author, Jonathan Fullam.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Tero Kadenius replied on Wed, 2011/02/23 - 1:06pm

I definitely agree about the importance of test readability. Unit pests kill TDD in no time! It seems that tests that are not written in TDD style are the worst. I'm not sure if that's because the writer doesn't have to think about the tests as requirements or just because developers who don't write their unit tests in TDD style are the ones who are not interested or competent in making good, clean tests in the first place.

Peter Arrenbrecht replied on Fri, 2011/02/25 - 8:09am

Going one step further you end up with literate testing, which focuses even more on the narrative and explanation, while still holding one accountable by requiring actual runnable tests.

Jessie Mear replied on Wed, 2011/09/07 - 6:46am

Often coders will look at the test code as unofficial documentation of how the real code works and should be used. java programmers

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.