Realize a vision, not a requirement spec

Most of us want to develop with quality. We want to create things that are really good, that work well, and that delight users and customers.

In order to do this, we come up with a number of practices, rules, policies, and other tools to ensure we stay on a good path. While all these can help us, they can also cause us to lose focus on the real goal. “You get what you measure”, is a common saying, one that also means that if you measure X in order to get Y, you will receive X but not Y if you push the measuring hard enough.

What I would like here, is to encourage you to take a step back, think about what you are doing and why. Is the thing that you are doing helping you reach “good” or just “done”? Are you improving the system or just extending it? Another way to put this, I want us to work on realizing a vision rather than a requirement specification. Everyone from developers and testers to architects and project managers should know and care for that vision. They should also have mandate to try their best to realize it.

As an inspiration, this is the “requirement specification” that Michelangelo received for his frescoes in the Sistine Chapel.

Please paint our ceiling for the greater glory of God
and as an inspiration and lesson to his people.

He did also receive a few suggestions for motives, but the above quote was the vision that Michelangelo was asked to realize. I think we can agree on that the result was more than “ok”!

The ceiling of the Sistine Chapel

The ceiling of the Sistine Chapel

Extract the logic (what’s left is glue)

 

Unit testing friendly code is code that has enough complexity and few dependencies. Therefore I would like to talk about a technique for massaging your code in that direction.

Separating logic from glue can make unit testing easier.Let’s say we have an important class with both high complexity and many dependencies. It is really in need of unit testing because of its complexity and importance, but is hard to isolate properly. Trying to unit test such a class typically leads to long tests that are hard to read and maintain, and that need a lot of complex set-up.

This is my “go to” method for handling this kind of situation.

  1. Extract the logic – move the pure, (mostly) dependency free code which performs the actual functionality of the system out into separate units. Unit test these new units as much as you want.
  2. What’s left is “glue” – the original code is now a “web” of dependencies that wire various units of logic together to perform what the user wants. Use integration or system tests to test this wiring.
  3. Improve the tests – write, modify, or delete tests as needed.

The result is code that follows a pattern that I call Logic+Glue.

Now, we will go through these steps in some more detail.

Extract logic

Of course, simply “extracting the logic” isn’t quite as simple as it sounds, most of the time. As a help, here is a general outline of the process I use to do it.

  1. Inline current methods into one large method. Do this within reason. If a method is recursive, or already dependency free, it might be better left alone.
  2. Extract local variables for all method calls. Each method return value should be assigned to a new variable. We do this in order to make it clear what data is actually used in our code.
  3. Treat any non-locally created data as dangerous. This includes constants, static fields, instance fields, parameters, as well as any object returned by a method call to such an object. These “dangerous” variable assignments are what will become the “glue”.
  4. Try to make all local variables final. The following steps will be much easier if variables are not reassigned. For the same reason, the method should have as few return points as possible.
  5. Extract blocks of logic into methods. Look at the code – whatever is not “dangerous” variable assignments is the actual logic. Look for for loops, if statements, blocks of non-dangerous local variable assignments, and so on. Such a block should not contain any of the “dangerous” variable declarations (but may use the variables!). Generally, we want as large blocks of code as possible that use as few variables as possible. Also, the more primitive (as in, using primitive data types) the interface is, the better. Use the “Extract Method” refactoring feature of your IDE to “preview” potential methods. Experiment, extract, inline, and extract again, until satisfied.
  6. Move methods of logic into new classes. Look at the newly created methods. They should now hopefully contain “meaty” logic but few or no references to class variables. If you realize, by looking at such a method that it would naturally fit in an existing class, move it there. Especially, see if it could fit in one of the parameter or instance variable types. Otherwise, create new classes and move a method, or a group of related methods, into it. Try to turn any static methods into non-static methods on the new class.
  7. Refactor and clean up. While doing the above steps, the code may get a bit messy. Now is the time to clean up the code you’ve extracted.

Feel free not to follow these steps if you feel you have a better way to do it, they are simply meant to be a help to get started.

What’s left is glue

Whatever code that is left in the class you started with becomes the glue. Ideally, this is now nothing but a bunch of the “dangerous” variable declarations and some calls to your newly extracted methods.

  • Refactor and clean up the glue code. Feel free to inline some of the variables or extract methods if it improves readability. The glue initially has the same interface as the old complex class. You can change this if you see room for improvements.

One way to verify how well we managed to extract the logic is by looking at the import statements of the glue class compared to the logic classes. Most of the import statements should be in the glue code, often from multiple different packages, whereas the logic classes should have rather short and homogeneous import sections.

Improve the tests

Finally, it is time to look at the tests. You have two primary strategies, which can be combined if wanted.

  • Write new tests. If you did this refactoring because the tests original tests were bad or non-existing, go ahead and write better ones for the newly extracted logic.
  • Keep the old tests. If the old tests worked well, you can choose to keep them since the glue is acting as a protecting layer between the logic and callers. They then become slightly higher-level unit tests where the “unit” now is a group of classes rather than a single class.

By doing this kind of extraction, you’ve moved your code base one step closer to a more testable code base. (Most likely, more in line with fundamental object oriented principles as well.)

Don’t prefix your test names with “test”

Please don’t start every JUnit test method name with the word “test“.

@Test
public void testParsingAnEmptyStringShouldReturnAnEmptyDocument();

I know JUnit used to require this convention in order to figure out which methods to run. That was before JUnit4 came out… 6 years ago. There is no need to include it any more.

@Test
public void parsingAnEmptyStringShouldReturnAnEmptyDocument();

We know it is a test from the @Test annotation just before it. Having every test method start with “test” is about as useful as having every method start with “method“. If everyone has it, there is no need to have it at all. The same goes for other prefixes, such as “verify“.

The same goes for the setUp() and tearDown() methods of JUnit 3. Now, we use @Before and @After instead, so please tell me what the method is doing instead.

@Before
public void initializeObjectDatabase();

@After
public void releaseFileHandles();

How unit testing changes your design

Lots of developers feel that unit tests are not only hard to write, but also are more of a hinder than a help when working with the code.

I think this comes largely from having code which is not “suitable” for unit testing, or put differently, that unit testing is not suitable for that code base. To get the promised value out of unit tests I think it helps to look at how unit testing effects the implementation code.

In my experience, whether some code is suitable for unit testing or not depends largely on two factors.

  • Does it have enough complexity so it is worth writing unit tests for?
  • Does it have few dependencies so that isolating it under test is simple?

While there are other factors that affect testability, I’ve found these to be the most important.

Enough complexity

The first major factor for testability deals with “is this code complex enough to need a test?” Not every line of code, every method, or even every class needs a separate unit test! This is, quite eloquently, summarized by Kent Beck, father of Test-Driven Development and JUnit.

”I try not to have more tests than I need.”
– Kent Beck

The typical example is a “getter”, a method which does nothing but returning a value of a variable. Does it need a separate test? I would say “no”. There are two primary reasons for this, in my mind.

  1. It is too simple to reasonably fail. In any case, the extremely occasional failure because of an invalid getter will most likely cost us much less than writing and maintaining unit tests for all getters.
  2. Other tests will cover that code. A getter rarely exists for itself. It is merely a method for some object to get information from another one. That information is then used for some computation or other purpose. The tests for that other code will test the getter “for free”.

Somewhat tongue-in-cheek, unit testing is like a grilling meat. There is no point in putting a bone without meat on the grill. (On the flip side, if you put too much meat on a weak grill, it won’t get properly done.)

If you develop using Test-Driven Development, you get this for free. Unless the getter is a major feature of your system, you probably won’t write code to tests that getter. You won’t do it because having that getter does not “drive” the design of the system, it is just an implementation detail.

Finally, it is not okay to keep a test for something that can’t reasonably break “just because”. It still takes time to maintain. If it doesn’t provide any real value, remove it!

Few dependencies

The second major factor for testability is about having few dependencies. It is so obvious it is often missed – the fewer dependencies, the easier to test.

As I said, it is really obvious. After all, the purpose of unit testing is testing a single unit. While doing so, we try to isolate that unit as much as possible. We want to test that unit, not the other next to it. This has lead to a big rise in the use of mocking frameworks such as Mockito and EasyMock.

But as I also said, it is so obvious that the real point is often missed. While we can fake dependencies during testing with frameworks, the best way to make isolating a unit easier is to reduce the number of dependencies it actually has! It doesn’t take a Mensa membership to figure that out, but for some reason (us being engineers, not philosophers) we forge ahead and try to solve the problem with clever tools without realising that we are solving the wrong problem.

Interestingly enough, fewer dependencies also means easier to reuse. Code with fewer dependencies is less tightly coupled to the specific application code, and instead deals with more general concepts in the model.

Implications on design

These two principles actually has some fundamental implications on the design of the code.

The classes in two code bases in which unit testing will be easy and hard, respectively, plotted on a graph with axes for “Number of dependencies” and “Code complexity” would look like this.

A graph displaying two possible code bases that are more or less easy to test.
Two possible code bases that are more or less easy to test.

As for the design and testing of a system, we see two clear trends.

  • Most complexity is in classes with few dependencies. Unit test this code as much as you want. Writing tests is easy because each unit is well isolated.
  • Most dependencies are in classes with low complexity. Test setup is hard for these classes. Consider not unit test these classes at all, instead focusing on automated integration tests.

Now I know that much (perhaps most) code doesn’t look this way. There is plenty of code which mixes complexity and dependencies. I believe this is unfortunate as it complicates unit testing and generally is harder to understand and work with. I think the two statements above are worth striving for. That will help a team to get true value out of their unit tests.

How to unit test code calling a static method

Common questions from people trying to introduce unit tests in a legacy code base are

“How do I unit test code which calls a static method?”

or

“How can I mock a static method?”

The situation often is like the picture below. We have a class that we want to test. We try to isolate that class as much as possible, but fail to properly isolate it because it makes call to static methods which has some side effects in the system.

A test for a class which calls a static method.
A test for a class which calls a static method.

Adapting the test leads to poor tests

While there are mocking tools which may fake these static methods, I feel that is the wrong way to go. This technique makes the test harder coupled to the implementation, because a large part of the logic from the static method now gets copied into the test setup.

Another option is to initialize the data needed for that static method to run, removing the need to isolate the class under test from the static dependency. This often includes setting system properties, or in a HTTP-based system, putting things on the session or request. Doing this ranges from inconvenient to virtually impossible, depending on how complex setup is needed.

All in all, I don’t believe these situations are best solved by being clever in the test.

Try turning the static method into a non-static one

The simple truth is that using static methods is basically not compatible with unit testing – static methods produce code with low “testability”. Therefore, the “obvious” and often best solution is to turn the static method into a non-static one. Let the class under test create its own instance of it, or provide an instance as a dependency. How to do this depends much on what the method does. If it has no side effects this is often rather simple, and this may be the best way forward. In some cases, you can move the method to one of its parameters. However, many times this is very hard, especially when the method has important side effects.

Wrap the static method in a wrapper object

Often, these static methods are old, complex, used in many places, and because of their static nature affecting the whole system. Perhaps such a method is responsible for returning a singleton object, keeping track of whether we are in some certain mode or not, or similar.

In these cases, a way forward is to create an intermediate object, a wrapper. This object takes the place of the class with the static method in the class under test, and in its first implementation it simply delegates to the static method in question. This wrapper object can then be provided as a dependency to the class under test. In the unit test, we now have the power to create a faked version of the wrapper which we provide to the class under test. This allows us to stub, spy or mock as much as we want. A setup like this for the above example could look as follows.

A test calling a class which calls a static method through a wrapper class.
Using a wrapper class to separate the class under test from a static dependency.

When we have created the wrapper, we can deprecate the old method, encouraging everyone to use the wrapper instead. After a while, when all invocations of the static method has been changed to go through the wrapper, we can re-implement the wrapper to provide an own, real implementation. Then, finally, we can remove the static method.

Possible drawback

Perhaps the most obvious drawback is that if we have a large number of static methods, we tend to get a large number of wrapper classes. This should hopefully be a temporary state until all invocations have been updated, though in many systems I can see how this would become a rather permanent state.

Actually deprecating the static method in favor of the wrapper could at least help to alleviate this somewhat, to make other developers aware of the wrapper’s existence. Another way to reduce the problem is to let a single class act as wrapper for multiple static methods. This of course works best if the methods are logically related.

Tell me what to expect

Working with a large code base, you get to see many different styles of unit testing. One of the aspects that I find interesting is the naming of the test methods.

Below are some examples of styles that I often come across. For the example, I use a hypothetical parser which is given an empty string as input.

testParse()

testParse_EmptyString()

testParseEmptyString()

parseEmptyString()

While all of these have their pros and cons, my primary objection is one they all share – they don’t tell me what should happen! They are as informative as writing assertEquals(actual) rather than assertEquals(expected, actual). I want to see something along the lines of these.

parseEmptyStringShouldReturnEmptyDocument()

testParse_EmptyString_EmptyDocument()

parsingAnEmptyStringReturnsAnEmptyDocument()

These variants tell me not only what the stimulus is, but also the expected outcome. I want it both. Stimulus and response. Input and output. Initial state and resulting behavior.

Another way to see it is that the tests become a requirement specification for the implementation. One could actually write the corresponding implementation code based on the latter test names, try doing that from the first ones.

The Test-Driven Development Duel

What I call the Test-Driven Development Duel (or test duel for short) is a simple and fun way to use test-driven development and pair programming together. It is all about challenging each other to implement tests with as little code as possible. The rules are rather simple, but surprisingly productive. It can be especially fun if you are somewhat competitive as a person. 🙂

  1. Alice writes a failing test, and hands the keyboard over to Bob.
  2. Bob tries to make the test pass with as little code as possible.
  3. Bob writes a new failing tests, and hands the keyboard to Alice.
  4. Alice tries make the test pass with as little code as possible.
  5. Restart from step 1.

Graphical representation of the TDD Duel rules.

  • Refactor now and then, as necessary.

This is also a very good way to teach test-driven development.

What, how, and why?

When I develop code, I find it helps to use the following rule of thumb:

What? Signature of the method
How? Body of the method
Why? Signature of the caller

That is, what a method does should be expressed clearly by its name or signature. The details of how this is done should be hidden inside the method’s body. Finally, the reason why the method was called should be given by looking at the caller.

What and how – information hiding

The perhaps most common mistake is to mix up the what and how. Common examples of this includes:

  • Throwing a low-level or vendor-specific exception from a high-level class, such as an SQLException from an entity manager or repository.
  • Unnecessarily returning a concrete implementation of an interface, e.g. ArrayList instead of List.
  • Excessive use of getters and setters, allowing the caller to “directly” modify the object, rather than providing methods to perform whatever the clients actually need.

This basically comes down to the principle of information hiding. In the above examples, the implementer has failed to hide implementation details from the caller and as a result it will be harder to change these methods’ implementation without also changing their signatures or callers.

What and why – reusability

Another common, although perhaps less so, problem is mixing what and why. I don’t think neither the method’s name nor body, should say attempt to answer the question why. That is, neither should not contain a reason, purpose, or justification for using it.

An example here is that we typically do not have separate classes named PersonList and CompanyList doing the same things with different kinds of data, but instead just a List<T>. Instead, it is up to each caller what the list is used for. (Unless of course a “person list” is an important concept in your domain, in which case it might be perfectly fine to have its own class.)

Letting a method specify why it should be called needlessly limits the applicability of the method and makes it less reusable. Different callers may use the method for different purposes (within reason) and that is perfectly fine. A method should just perform an action and let the caller worry about the reason for doing so.

A great example of the what and why separation, is the stack trace. Looking at a stack trace should in theory allow one to completely understand what is happening in a system. We know what was supposed to happen by looking at the currently executing method’s name and the exception. By then following the names on the stack all the way back to the root, a good stack trace allows us to understand why each step in the chain was taken. This actually applies to every level of the stack trace.