Monday, September 12, 2005

a Set of Unit Testing Rules

From Michael Feathers weblog:

A test is not a unit test if:

  • It talks to the database
  • It communicates across the network
  • It touches the file system
  • It can't run at the same time as any of your other unit tests
  • You have to do special things to your environment (such as editing config files) to run it.

  • True, but communication to DB, over network, must also be Unit-Testable.
    Probably a categorization fast/slow, partial/full, should also be done.

    Michael answer to these points:

    > Sometimes, your unit test must do some of these things:
    > 1. You test a class who's function is to interact with a
    > db, write/read a file, or write/read the Windows
    > Registry.

    I'm pig headed, I write them but I don't call them UTs when I'm with a team. Say that we are working test first and we discover we need to save things in the registry. To me it's best to think about what we need more abstractly, we just need a place to store things and chances are it doesn't need to be hierarchical in the beginning. So we can develop that abstraction (which probably looks as simple as a map) and it's guaranteed to be easier to use than the Windows registry.

    If we go that route, we make an implementation of that abstraction that works in memory for testing and one that translates its calls to the Windows registry calls.

    > 2. You develop a client; to make sure it works, it
    > must interact with a server. At my work, for
    > example, our client must exchange timestamped, signed, XML
    > messages with a server. The test will not be complete
    > without server interaction. Actually, you simply
    > cannot test this without a server.
    >
    > You want to say these are not unit tests? I'll argue that
    > the tests can't be any simpler.

    I agree that they are necessary, but I really like to see what can be done to strip logic away from I/O for the UTs. Other tests can handle the collaboration and the tests that actually touch the database or the the server, they have tests too, but there are in some netherworld in my view. In general, I don't think there should be many of them.

    I think that the main point is that we should use abstractions, "interfaces" in our program. It doesn't matter where the SmartObject.IsFunky gets his information, as long as he can answer the question "IsFunky". And this point of view should be seen in the UnitTests as well.

    No comments: