Project guidelines

Just some thoughts, mostly for my own benefit. I reserve the right to change my mind, and even do complete U-turns where necessary.

  • Use CruiseControl, or some other form of continuous integration.
  • Use clover, and fail checkins if there is any code not covered by a unit test.
  • Block System.out.println with a CVS commit script.
  • Ban unit tests from hitting the database.
  • Don’t write tests that require more than 10 lines of (non production) setup code per test method.
  • Don’t write code that requires a (JUnit) setUp method that is bigger than all your test methods combined.
  • Use mock objects very sparingly. Consider them indications of code smell.
  • Don’t use anonymous subclasses in testcases just to loosen method permissions for testing, or to stub out hard-to-test behaviour. Code smell warning.
  • Do put your test code in a parallel directory structure, in the same packages as your production code.
  • Do test protected and package methods.
  • Don’t worry about testing private methods too much – they must be called from a public, package or protected method, or they’re redundant and can be deleted.

8 thoughts on “Project guidelines

  1. I’m glad you reserve the right to make U-turns – mock objects are incredibly useful. They’re indications that your code is disconnected, which is a good thing. 🙂

  2. >>I reserve the right to change my mind, and even do complete U-turns where necessary.<<

    Ahhh spoken like a true project manager and developer…..

  3. — Ban unit tests from hitting the database.

    May I ask, how to avoid that one ?
    And why ?

  4. Overall quite a good list! Don’t use mock objects however? That’s a silly rule. What on earth is the reasoning behind it?

    We have hundreds of mock objects usages in our test suite, and they’re a perfect example of your code BEING decoupled which (as Joe said ) is a GOOD thing?

    Mike

  5. Ask yourself why you need a mockobject. If your code is nicely separated into interface/implementation, can your testcase not implement the interface that you would otherwise write a Mockobject for and pass itself to the object under test?

  6. Good list, I think my personal inclinations match up pretty well. Agreed about MockObjects – I have one servlet in my app, and the lines of code it contains seem to shrink almost daily because of refactoring. Of course there’s really no other way to test a servlet without mockobjects — unless you use in-container testing, which I’m getting more and more convinced is something to avoid where possible.

  7. What if you are testing persistence? What if you are testing a complicated DB query? You HAVE to allow testing of the database. Furthermore, a test may only be runnable when a certain set of complex conditions exist. Establishing these conditions can require much more code than the test itself. In fact, most tests I’ve written are 80% setup. You set up the conditions for the test, and then call one method and examine the results.

    You really don’t want to be telling your coders (who you are lucky enough to have writing tests at all) to remove test code.

    Perhaps you need to find metrics for your test cases not involving lines of code, but rather the quality of the tests themselves. Most line of code metrics are usually braindead and a stopgap for a _real_ quality metric.

  8. Dave,

    In my opinion, you shouldn’t be testing complicated DB queries in your unit tests. A unit test should test a ‘unit’ of code.

    If you want to test your DB query, test that the correct prepared statement is called, but to actually call the database will take too long for a unit test, and depends on your database being setup. An acceptance test maybe, but not a unit test that you want to run 100 times a day.

    Regarding huge setup methods – I believe that this is a sign that the code is too highly coupled. Your class shouldn’t need 100 things setup to be tested (ideally).

    I also think that mock objects are a very nice way of abstracting the container and testing code that has been written using inversion of control.

Comments are closed.