Thursday, December 10, 2009

Intimate Tests

So I have been trolling through code on my current project lately checking tests and test quality. One of the things that I have been seeing a lot of lately involves tests that have what I consider to be too intimate knowledge of the classes they are testing.

When you write *good* tests using TDD you test the expected behavior of the method/class. Done correctly you will create the failing test, make it work, and then refactor intelligently for clarity and better design. This is not a revelation to anyone doing TDD or experienced in agile practices.

What I find is that much of the code I am reviewing seems to be characterization tests that were retrofitted onto the code for coverage purposes more than real *testing*. By this I mean the class was written first or in conjunction with the tests and that the tests verify the execution of the code rather than a behavior or expectation.

The result ends up being a test that has way more knowledge of the implementation of a behavior than it should. It also results in bad design.

A good example is a Portlet servlet. A servlet is built to support the rendering of a portlet and without doing TDD up front what resulted is a servlet class that implements most, if not all, of the business logic. This results in two big issues. First, the business logic gets tied tightly to the portlet and servlet specs and requires a lot of mocking of requests, responses and session objects and the method invocations. Big pain  in the a**.

Second, because the logic is in the servlet, you miss the opportunity to place the logic in a service/bean class where it belongs. That class would be much simpler to test.

More importantly, if the logic is separated out properly you have the ability test the behavior instead of the implementation as you no longer need to worry about the container details that waste your time. No effort spent setting up the container state, you only focus on the business logic.

This also means you can better test *what* you want to do rather than worrying about *how* it is done. You can focus on the results and refactor without fear when green.

I am sure you can think of dozens of examples of this yourself. I find this tends to happen because a) the developer is new to TDD (or isn't experienced) and/or b) there is a strong push for getting coverage on the code rather than pushing for quality tests (which will result in good coverage.)

No comments:

Post a Comment