Retrospectives

Iterations are the heartbeat of agile–a consistent pulse, something that can be measured. If iterations are the heartbeat, the heart is retrospectives, representing the core and true spirit of agile: How do we adapt, how do we continually improve?

Too many teams don’t run retrospectives, and many of those that do fall off quickly. Often they fell into the trap of running a consistently boring meeting: What things did we do well, what things do we want to improve upon? Worse, they treated the outcome of the retrospective as a bunch of vague promises. I’d certainly stop attending them if that’s all they were.

A solution to the first is the Esther Derby/Diana Larsen book, Agile Retrospectives. The biggest value of this book is that it provides a number of activities to help you run your retrospectives. It provides a great starting point to devising your own activities–being creative is an important way of keeping people interested in attending retrospectives. There are a number of areas that remain to be explored with respect to retrospectives. For example, I’m currently continuing to explore distributed retrospectives.

With respect to the second challenge–lack of commitment–I like treating the retrospective items as stories, or experiments, that are introduced for the upcoming iteration (but these are not project stories). Thus acceptance criteria are required, and the stories must be specific, concrete things that people will (or won’t) do. During the subsequent retrospective, the team can’t consider the experiment complete if the acceptance criteria has not been met, and thus shouldn’t base subsequent actions on that experiment.

There’s always someone who wants an agile litmus test. “You aren’t agile if…” I feel comfortable in saying that “you aren’t agile if you aren’t consistently doing retrospectives and adapting the process based on them.”

Violating Standards in Tests

Should your test code be subject to the same standards as your production code? I believe there should be different sets of standards. I am collecting interesting idioms that are normally shunned in good production code, but are acceptable and advantageous in test code.

An obvious example is the use of macros in tools like James Grenning’s CppUTest. The testing framework (an updated version of CppUnitLite) requires programmers to use macros to identify test functions:

TEST(HelloWorld, PrintOk)
{
   printHelloWorld();
   STRCMP_EQUAL("Hello World!n", buffer); 
}

No self-respecting C++ programmer uses macros anymore to replace functions; per Scott Meyers and many others, it’s fraught with all sorts of problems. But in CppUTest, the use of macros greatly simplifies the work of a developer by eliminating their need to manually register the name of a new test with a suite.

Another example is the use of import static in Java. The general rule of thumb, suggested by Sun themselves, is to not overuse import static. Deleting the type information for statically scoped methods and fields can obscure understanding of code. It’s considered appropriate only when use of static elements is pervasive. For example, most developers faced with coding any real math do an import static on the java.lang.Math functions.

However, I use static import frequently from my tests:

import static org.junit.Assert.*;
import org.junit.*;
import static util.StringUtil.*;

public class StringUtilCommaDelimitTest {
   @Test public void degenerate() {
      assertEquals("", commaDelimit(new String[] {}));
   }

   @Test public void oneEntry() {
      assertEquals("a", commaDelimit(new String[] {"a"}));
   }
   ...
}

Developers unquestioningly use import static for JUnit 4 assertions, as they are pervasive. But the additional use here is for the method commaDelimit, which is defined as static in the target class StringUtil. More frequently, I’ll have the test refer to (statically defined) constants on the target class. For a test reader, it becomes obvious where that referenced constant would be defined.

What other coding standards are appropriate for tests only, and not for production code?

Test Abstraction

I’m staring at a single CppUnit test function spanning hundreds of source lines. The test developer inserted visual indicators to help me pick out the eight test cases it covers:

//++++++++++++++++++++++++++++++++++++++++++++++++++

Each of these cases is brief: four to eight lines of data setup, followed by a execution statement enclosed in a CPPUNIT_ASSERT. Of course they could be broken up into eight separate test functions, but otherwise they are reasonable.

Prior to the eight tests there are two hundred lines of setup code. Most of the initialization sets data to reasonable default values so that the application code won’t crash and burn while being exercised.

I don’t know enough about the test to judge it in terms of its appropriateness as a “unit” test. It seems more integration test than anything. But perhaps all I would need to do is cleverly divorce the target function from all of those data setup dependencies, and break it up into eight separate test functions.

The aggregation of tests is typical, and no doubt comes from a compulsion to not waste all those 200 lines of work! The bigger problem I have is the function’s lack of abstraction. Uncle Bob always says, “abstraction is elimination of the irrelevant and amplification of the essential.” When it comes down to understanding tests, it is usually a matter of how good a job the developer was at abstracting intent. Two hundreds of lines of detailed setup does not exhibit abstraction!

For a given unit test, I always want to know why a given assertion should hold true, based on the setup context. The lengthy object construction and initialization should be encapsulated in another method, perhaps createDefaultMarket(). Relevant pieces of data can be layered atop the Market object: applyGroupDiscountRate(0.10), applyRestrictionCode(), etc. Not only does it help explain the data differences and correlate the setup with the result, it makes it easier to read the test, and easier to write new tests (reuse!).

I often get blank stares when I ask developers to make their tests more readable. Would they respond better to requests to improve their use of abstraction?

Code to Discuss

A good software team knows to talk openly about the code. One suggestion is to get together once a day, maybe at day end, to just talk about or look at some code, even if you are already pairing. The get-together need not take long nor be formal in any manner. Fifteen to thirty minutes should be sufficient. Toss some code up on the wall using an LCD projector and have at it.

Initially, such discussions can be touchy, as critique can be mistakenly viewed as insults or attacks. Over time, the regular exercise of discussing code should form a group that better understands how to communicate effectively with each other.

What to talk about? I brainstormed some ideas for a specific set of teams, things I knew they needed to discuss, and provide that starter list here. Given the almost limitless number of reasons to talk about the code, there is little excuse to forego the forum.

  • “here’s something cool that I did today!”
  • “how could I better express this test?”
  • “here is a mocking technique I found valuable”
  • “this test didn’t make sense to me”
  • “this area of the code concerns me”
  • test granularity
  • test naming
  • BDD
  • how TDD changed my design
  • naming standards
  • coding standards
  • warning standards
  • JUnit 4.4+: Hamcrest matchers, theories, etc.
  • “we’re not writing enough tests”
  • code coverage (taking a look at the actual lines exercised by tests)
  • WTFs in the code or test. Can be amusing, but watch the toes!
  • test execution speed. Splitting into slow/fast suites.
  • identifying and speeding up slow tests
  • test smells
  • various forms of test double (see XUnit Patterns)
  • simple design vs SOLID
  • “we’re not refactoring our production code enough”
  • “we’re not refactoring our tests enough”
  • object mothers for tests
  • “the build is a pain in the rear”
  • looking at a new mock tool like Mockito

And so on. Perhaps get a volunteer (or two) to “open” a topic each week. They talk for a few minutes, and then you open things up for group discussion.

Atom