TDD Lesson 1 – Don’t worry about starting small

The first thing I want to cover in my “learning TDD” track is to not worry about writing seemingly meaningless or uninteresting code. First of all you never know what shape code will take in the future – the simplest of tests might help prevent a subtle bug. Secondly, it won’t be long before you start to write more interesting code, so hang tight!

That said, for the first couple minutes I didn’t even know HOW to start. I knew that I wanted to start with a core class in my domain (an Indicator). Indicators do all sorts of interesting stuff, but since I’m writing tests first, I don’t even have an Indicator class!  To solve that little problem, I wrote the only test that made sense:

[TestFixture]
public class IndicatorTest
{
 [Test]
 public void CanCreateIndicatorInstance()
 {
  Indicator indicator = new Indicator();
  Assert.IsNotNull(indicator);
 }
}

Of course the code won’t build. So I create a new class “Indicator” and make sure the default constructor is there. I know that in theory you’re supposed to make the test fail – but making my constructor throw a fake exception for the same of making it fail doesn’t seem worthwhile. It’s entirely possible that I’ll opt to go with only factories for my Indicator class, but for now, this is the quickest way to get started.

Next, I know that every Indicator will have an Name, so I write my next test:

[Test]
public void CanSetIndicatorName()
{
 Indicator indicator = new Indicator();
 Assert.IsNull(indicator.Name);
 indicator.Name = “Test Indicator“;
 Assert.AreEqual(“Test Indicator“, indicator.Name);
}

So I go into my Indicator class and create a straightforward private _name field with a public Name property. Two points here. I could have easily made the test fail, but figured the broken build was good enough. Also, I agree that a public field would be the simplest solution here, but that violates our coding standards.

The Indicator class has a number of similar properties, so I write similar tests for all the ones I know about. Admittedly it isn’t particularly fun and it doesn’t feel too productive, but it’s only a couple minutes of my time. There’s an urge inside of me pushing me to take a bigger leap, but I keep it in check.

That’s it :) I know it isn’t much, but I had such a hard time accepting this way of starting, I figured others might also. I promise things will quickly get more interesting (though I think next post I might take a little break and go over nANT and CruiseControl.NET).

On a side note, as much as people talk about the importance of unit tests when it comes to refactoring, I honestly see them as even more useful when working in a team. The CanSetIndicatorName test tells the other developers on the project that someone expects the Name property to be null and NOT string.Empty when a new instance is created. If anyone changes my field declaration to _name = string.Empty, the test will fail and hopefully they’ll think twice about their change, else risk breaking code somewhere they weren’t away of.

[tags: Agile, TDD, .NET]

This entry was posted in TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

8 Responses to TDD Lesson 1 – Don’t worry about starting small

  1. raffourtit says:

    About the first test.
    When doing new development it might be a bit overdone. But I’ve just started adding unit tests to existing code, in that case creating the first test can already be quite tricky. And especially when starting with TDD I can see the point of making it (just to get the feeling of having somewhere to start). Working with a testing framework is something else then reading the tutorials.

  2. karl says:

    Tim:
    I certainly agree with you for complicated tests, but isn’t it just overkill for these simple examples? Isn’t Jeffrey’s “common sense” approach better here (I’m asking sincerely).

  3. Tim Dallmann says:

    When you say: “I could have easily made the test fail, but figured the broken build was good enough.”, I think you’re missing the point. The initial failure verifies that when your test actually fails, your test harness will report that failure. The broken build failure doesn’t catch this. Without using the “Red” step of “Red-Green-Refactor”, you risk having tests that appear to run successfully, even when they have actually failed. It may seem silly and trivial, but it’s useful nonetheless, especially as your tests get more complicated.

  4. I know there is a lot of dogmatism around TDD for some folks. The key to remember is that automated tests as a whole are assets that can be used continually to verifiy code. Unit tests help to localize a failure. The more I do TDD, the more pragmatic I become about it. I tend to fudge the lines a bit and don’t keep religiously to Kent Beck’s guidelines. If a test creates a safety net under a bit of code, then I consider it beneficial. I’m using common sense as my guide more and more.

  5. Haacked says:

    I agree. You want to keep your fine-grained tests because when a more complicated test blows up, if the fine grained test still passes, you can exclude that from the cause. But if it fails, then it is the likely culprit.

    Removing the assert is probably wise as it just takes up space.

    However, if your test is to make sure that your class has a default public constructor, I would probably name the test accordingly or put a comment there.

    [Test]
    public void CanInvokeIndicatorDefaultConstructor()
    {
    new Indicator();
    }

    or something like that.

  6. karl says:

    Nat & Haacked:
    Thanks for the input, as this is a learning experience, I appreciate it!

    I agree that it’s a little silly, but not completely useless. You’ll always have some unit tests that are going to be more complex than others and as such they’ll implictly test other functionality. Should the simpler unit tests be elimited because the code is covered elsewhere?

    The first test also tests that the Indicator class has a public default constructor. That very well my be a required behaviour. Again, other tests are bound to cover that functionality, but I must say I enjoy having a test devoted to it. It sends a pretty clear message about the need to have it.

    Nat, you are right though, I could (and maybe should?) remove the Assert. If the code (a) compiles and (b) doesn’t throw an exception I know I’m ok.

  7. Haacked says:

    The first test isn’t completely useless as it does test that the constructor doesn’t throw an exception. If it did, the test would fail. And yes, the second test would also fail if the constructor threw an exception, but the *granularity* of that test is less than the first test.

    However, I do tend to agree that writing a test before you have a class to test might be a bit overkill. I usually at least create the class and a stub method or property that throws a NotImplementedException().

    You can see my approach in this post (the topic is on something else, but I happen to demonstrate my TDD approach as a side effect).
    http://haacked.com/archive/2006/06/23/UsingRhinoMocksToUnitTestEventsOnInterfaces.aspx

  8. Nat says:

    There is no point in the first test. Firstly, you’re not testing anything that isn’t tested in the second test. Second, it’s testing the behaviour of the new operator and nothing else: new is *guaranteed* never to return null, so the assertion is unnecessary noise.

    In fact, the first test *decreases* the quality of the code. Unnecessary tests increase the maintenance burden because they make it harder to find the tests that actually are specifying required behaviour.