30

In recent years, I have only written small components for people in larger projects or small tools. I have never written a unit test and it always seems like learning how to write them and actually making one takes a lot longer than simply firing up the program and testing for real.

I am just about to start a fairly large scale project that could take a few months to complete and whilst I will try to test elements as I write them (like always), I am wondering if unit testing could save me time.

I was just wondering if anyone could give good advice:

  1. Should I be looking at unit testing at the start of the project and possibly adopt a TDD approach.
  2. Should I just write tests as I go along, after each section is complete.
  3. Should I complete the project and then write unit tests at the end.
wilhil
  • 992
  • 1
  • 9
  • 14
  • 1
    Related: (http://programmers.stackexchange.com/questions/10849/unit-testing-newbie-team-needs-to-unit-test) – Beofett Mar 31 '11 at 14:15
  • 1
    Related: http://programmers.stackexchange.com/questions/41196/tdd-with-limited-resources/41213#41213 – dietbuddha Mar 31 '11 at 17:00
  • possible duplicate of [What should you test with unit tests?](http://programmers.stackexchange.com/questions/750/what-should-you-test-with-unit-tests) – gnat Feb 20 '15 at 12:57

4 Answers4

30

Some will say otherwise but I would suggest that you separate TDD and Unit Testing. TDD is quite a mental shift and unit testing appears initially to take time. If you consider them to be one item, there's a risk that you won't see enough benefit immediately and there will be a temptation to simply drop TDD and Unit Testing with it.

First thing is to write some Unit Tests. They don't have to be perfect at first. Just teach yourself how to test small units of code and how to use mocking to isolate components.

This is the biggest time-taker but has by far the biggest payoff. Once you notice that you no longer have to page through 14 web pages to get to the one you want to test, you'll know what I'm talking about.

For me, the big Eureka moment was a Windows app where I was trying to test a regex which required I fill in two forms before I could get to it. I installed NUnit and wrote a test around that method and saw how quickly I saved hours of testing time. Then I added more tests to deal with the edge cases. And so on.

Then learn to write unit tests well. Learn the balance between brittle tests which are quick to write and writing many many individual tests. This is fairly easy. The lesson is that ideally each test only tests one thing, but you quickly learn how long that takes, so you start bending a bit on the rule until you write a test which breaks on every code change, then you move back towards the right balance (which is closer to the former than the latter).

TDD is, as I said, a major mental shift in the way you work. However, it won't add much time to your development process once you're already writing tests anyway. And you will, I promise, see your coding style improve before your very eyes. Or rather, if you don't then drop it, it's not for you.

One last thing to bear in mind is that TDD is not limited to unit tests. Acceptance test driven design is every bit a part of TDD. Another good reason not to mix them up in your mind.

pdr
  • 53,387
  • 14
  • 137
  • 224
  • +1 Thanks - Leaving open for a while in case of other answers, but I think this project will be my turning point for me on the same grounds - multiple web pages and it will take a lot longer to manually test. – wilhil Mar 31 '11 at 14:36
  • @pdr do you have some references I can study on "writing unit tests well"? – Gaston Oct 22 '14 at 15:20
9

I agree with the others (definitely don't write your tests at the end, TDD takes time to learn, start with testing however you can, aim for full TDD eventually). But I wanted to add one thing in response to your comment: "I am wondering if unit testing could save me time."

My answer is an unequivocal yes. I learned the TDD approach circa 10 years ago, after a similar amount of time coding without tests. These days, if I'm doing something short (<250 loc) and simple, or something throwaway, then I won't TDD it. Otherwise, I do, and precisely because it saves time.

The time savings comes in three ways: less WTF, less debugging, and less fear. The first is obvious: you spend a lot less time wondering what the hell the thing you built is doing. When you do have an issue, debugging is much easier, because a) you catch tested bugs instantly, and b) untested bugs have fewer places to hide.

The less fear thing, though, it more subtle. Until you've spent a while in a TDD code base, you don't even realize how much time you spend worrying about changes you're making. Does X work? Will it break Y? Is there some Z that might be affected? With TDD, that goes away, because you turn your fears into tests, and then the computer automates the worrying. A braver developer is a faster developer.

William Pietri
  • 3,060
  • 1
  • 17
  • 20
5
  1. Should I be looking at unit at the start and adopt a TDD approach.

  2. Should I just write tests as I go along after each section is complete.

Either of these, but not the third option.

As @pdr noted, learning proper unit testing takes time. You definitely want to take your time to learn at the beginning of the project lifecycle, not towards the end when the deadline is looming over your head. This way you are already up to speed, and may even start reaping the benefits by the time the deadline gets closer, due to having caught most of the bugs earlier in the project lifecycle.

Note that the very first unit test is always the most difficult, especially if you are testing code already written. Such code may not be unit test friendly, so you may have a hard time wiring up all the objects with the proper state for the test. Thus pick some easy, fairly isolated, low level test for your first unit testing attempts, then gradually you may increase the level of challenge. Once you have the first test fixture ready, the next test case is much easier, and by the time you get to the fourth, you will be producing test cases like on a conveyor belt. That's when you start to feel the goodness of being able to repeatably, demonstrably prove that your code works...

I personally prefer the TDD approach and I don't think it is that challenging - it does take perseverance, but I believe the sooner you start with TDD, the sooner you start to see the benefits of unit testing overall. However, it may be that the first few unit tests are better to write for code you already have. Then once you get the hang of it, you can start experimenting with TDD.

Péter Török
  • 46,427
  • 16
  • 160
  • 185
  • I think I will be going for the second option based on yours and PDR's advice - for option three, I really meant I would be doing manual testing and just writing a test at the end to ensure everything is complete the way it should be and to test against if there were any modifications in the future. – wilhil Mar 31 '11 at 14:38
2

I think the best thing for a newbie to do is to tackle some code katas that lend themselves to unit testing. For example; validating an e-mail address. TDD becomes the natural flow once you've tackled a few of these Code Katas. Check out the following code kata for the e-mail address validator I mentioned: E-mail Validator

For an explanation of what Code Katas are for those of you who don't know, check out the following link: Code Katas

Pramod
  • 103
  • 4
Anish Patel
  • 229
  • 1
  • 2