Tuesday, July 29, 2008

Behavior-Driven Development to the Rescue?

I've been trying to wrap my head around how I can increase LinFu's test coverage rate for over a week now, and I have to admit that doing DDT testing (aka TDD in reverse, or post-hoc unit testing) is much more difficult than its TDD counterpart.

In contrast, TDD seems to apply a bottom-up approach to ensure that each component is functioning, and in LinFu's case, I'm going to need a top-down testing approach to ensure that all of LinFu's features work as advertised. My intent is to write each test as a specification for LinFu's behavior, and each one of these tests will ensure that LinFu behaves according to its specification.

It's by no means perfect, but it's the only practical solution that I can apply to the existing code base without having to rewrite it. At best, it seems like an ugly hack since I'll be effectively doing black box testing against LinFu instead of getting the 100% test coverage.

The other alternative, of course, is that I can do a complete rewrite of LinFu (presumably version 2.0) from scratch. (It's not a pretty option, but then again, it's no better than having to do post-hoc unit testing).

So here is my question for the developer community at large: Which option should I take, and why? If I do LinFu v2.0 with a 100% test coverage rate, will that up the adoption rate, or will LinFu v1.0 with specification tests added be sufficient enough to fix the test coverage problems?

10 comments:

  1. I strongly opt for a TDD re-write. At the same time you will see that much refactoring is automatically needed to achieve good testability. As a benefit you'll get good SoC.

    ReplyDelete
  2. I like the TDD rewrite. If you start with the tests you can probably take a lot of the same functionality out of your current version. Plus the tests will not feel like their tacked on after the fact. Either way though, it's great that you're focusing on getting some tests around the functionality.

    ReplyDelete
  3. Ok, so just to clarify, when you both say "TDD rewrite", do you mean rewriting LinFu from scratch with TDD built in from the start, or did you mean LinFu 1.0 + Additional Tests?

    If you mean a complete rewrite, then I'm going to redo LinFu's DynamicProxy and write LinFu.DbC3 so that every subsequent library will be using DbC by default, in addition to the 100% test coverage that will come with each project.

    LinFu v1.0 gave me a great idea of how to put the overall architecture together, and this might just be a step in the right direction.

    That should take care of any future testing issues that LinFu might have, and finally I'll get some third party adoption going on :)

    ReplyDelete
  4. +1 for the TDD rewrite. Consider LinFu v1 a spike, if you will, for the functionality you were looking to achieve. Write the new version using TDD and you'll find more often than not that you're going to have a lot less code that's well factored with good separation of concerns / IOC in order to achieve testability. (if you use a mocking framework, pick one that won't let you get away with bad practices like Moq or Rhino Mocks) I'm sure it's pretty painful to get this sort of feedback so late in the game, but you have some gems here that need to make it out to the larger community. I have nothing but respect for you in taking on this challenge. Oh, and you've got the Google Code site - use it for everything it's got - take a look at Autofac (http://code.google.com/p/autofac) and how he's using the site - wiki, issue list, etc...

    ReplyDelete
  5. I agree, I think the TDD rewrite is a much better option.

    The code will naturally be more malleable and likely leaner, after wards. If you add tests afterwards, you may find yourself testing a lot of things you didn't actually need in the first place.

    jeremy

    ReplyDelete
  6. Whatever works you.
    I will use it anyway :-)
    I am already using in my production code your LinFu Delegates library v1, which enables me to do magic.
    Thanks!
    Omer.

    ReplyDelete
  7. @everyone:

    Ok, then a rewrite it is. I'll keep posting frequent LinFu v2.0 updates on this blog. Thanks for the feedback!

    ReplyDelete
  8. Count another one for a rewrite (although the vote's over). The second time around you know what functionality you need and what to expect, so a TDD rewrite will take less time than you'd think.

    At any rate, the relative lack of test coverage is keeping me from using LinFu in a commercial project right now :(

    ReplyDelete
  9. Just to be clear, it isn't like there is some kind of incompatibility between doing your rewrite (for the purposes of cleaning up architectural and other issues) and going BDD. In fact, after starting to go BDD after a few years of TDD, I would highly recommend a BDD re-write.

    The BDD vs. TDD distinction is more about the angle you view the effort from and the way you express your requirements in how you structure your test fixture classes and test methods. Consider it as more of a refinement of TDD, rather than as some entirely different animal.

    ReplyDelete
  10. To be clear, when I said "I would highly recommend a BDD re-write." I wasn't suggesting that you necessarily need to do a re-write at all, rather that if you had already decided on doing a re-write, BDD would be the way to go.

    ReplyDelete

Ratings by outbrain