90

I assume that my project is decoupled enough to allow for unit testing. But how big, exactly, in terms of clases and functions does my project need to be to make unit testing worthwhile?

We all make mistakes and no one's perfect, but I consider myself a decent programmer to handle small projects' errors with stepping through. Or is unit testing a hard necessity no matter of what size your project is?

12
  • 26
    The big incorrect assumption you're making is that the project is only for you and that it's only for now. What if you leave it for a few months, do something else, then come back to it? Will you have the same confidence about being a "decent programmer" (which has nothing to do with whether or not to test)? What if someone else takes over your project...? A great blogger (sadly no longer active) wrote that you should always "cater for the code reader, not the code writer". Commented Aug 8, 2012 at 8:41
  • 6
    How about this (meant for C#.NET): int x = 3 * (1 / 3); what is value stored in x after the operation completes? My point is even one line code may require testing because it could lead to a bug, either because you don't know or because you know but did the wrong code.
    – NoChance
    Commented Aug 8, 2012 at 8:46
  • 2
    @aaamos, I think you missing my point. The fact that I am asked this question alone shows that I consider catering for the code reader as well. Commented Aug 8, 2012 at 8:51
  • 14
    Having done it both ways, I can tell you its so much easier to write the tests as you are going along (i.e. while the project is small) than to go back and write unit tests later when you feel the project has met some arbitrary "we should write tests now" condition. Commented Aug 8, 2012 at 12:06
  • 1
    You're asking the wrong question. It doesn't matter how big the project is. The question is, how much do you care if it's correct? If correctness is important, than unit tests are an effective way to improve correctness. Commented Jan 14, 2013 at 6:13

12 Answers 12

213

Your project is big enough already.

In my experience, one class and one function have been sufficient to consider the need for unit testing.

    class Simple {
        boolean reallySimple() {
            return true; // how do we make sure it doesn't change to false?
        }
    }
    
    
    class SimpleTest {
        void assertReallySimple() {
            // ensure reallySimple return value isn't changed unexpectedly
            UnitTestFramework.assertTrue(new Simple().reallySimple());
        }
    }
17
  • 24
    Surely you should start earlier, at the 0 class/0 function point... if you're following TDD :)
    – Kaz Dragon
    Commented Aug 8, 2012 at 12:52
  • 118
    +1. If you program is big enough to have bugs, it's big enough to have unit tests. Commented Aug 8, 2012 at 14:03
  • 9
    @JasonOrendorff: I'm mocking that up into a poster and putting it in my office. Brilliant. Commented Aug 8, 2012 at 14:50
  • 8
    While I don't necessarily disagree with the sentiment, if your code is really that simple you could probably get away with just assertions instead of full blown unit tests.
    – Chuu
    Commented Aug 8, 2012 at 21:26
  • 2
    I gave you an upvote for the headline, but your example is more an example which shows some unit tests are pointless. I guess it could be improved by using a pseudocode function like AtLeastOneLineFunctionWithEnoughCodeToOverlookATypo().
    – Doc Brown
    Commented Dec 4, 2015 at 8:56
114

I've never bought into the "you must unit test everything" idea, though there are certainly folks out there who have (see gnat's answer!).

As far as I'm concerned, the main benefits of unit testing are:

  1. Helping ensure changes don't break things.
  2. Helping you design sensible interfaces to your classes (since it forces you to be a client to your own code).
  3. Helping document how your code is expected to be used.

Basically you need to weigh the time it will take you to write & maintain tests against these factors.

Number 1 is usually sufficient to make it worth writing tests. In my experience, >95% of code gets modified sooner or later.

6
  • 9
    Agree with this - when working in a single developer shop you need to strike a balance between software quality and testing everything (which can take up a lot of your time). Don't forget that everytime you make a change you may need to modify your unit tests to suit
    – Matt Wilko
    Commented Aug 8, 2012 at 10:53
  • 1
    You shouldn't test everything, but you should test any behavior that's exposed to the outside world. There is/are certainly maintenance costs to testing, and as Kent Beck said in some SO answer (I think it was SO) - test enough to make you confident that your code is correct. Commented Aug 8, 2012 at 11:44
  • 11
    I'd add that if you're only doing minimal automated testing, unit tests are the wrong level to target. Instead go for high level integration/smoke tests that push a few data sets through your app end to end without mocking anything. You want these tests to exercise as much of your codebase as possible and cover all the normal use cases and execution paths. A 75% chance of knowing your changes broke something, somewhere, in the app is more beneficial than a 5% chance of knowing you broke SomeClass.OneOfTheHandfulOfTestedFunctions(). Commented Aug 8, 2012 at 12:30
  • 3
    Uh, I think you missed one: "Making sure the code works the way it's supposed to!" Commented Aug 8, 2012 at 16:40
  • 3
    @BlueRaja-DannyPflughoeft: Actually, it would be more accurate to say: "Making sure the code passes the unit tests you've written!" Commented Aug 9, 2012 at 15:53
36

It's simple: you don't need unit testing if you will discard the program after running it once.

If this seems excessive to you, consider what the alternative would mean. If there were some size below which unit testing doesn't pay, you would have to keep judging in your mind: "Have I reached the magic size yet? Should I start writing tests?" Now, programmers are notoriously bad at predicting the future, and they are notoriously bad at judging their own skill. Code that looks crystal-clear to you now will become incomprehensible, even to you, even by waiting a month. A project that you are absolutely, positively certain will never be used again, and that you keep around merely on the remote chance that you might want to look up how you solved something before, will be requested again, and will receive change requests.

It is therefore very likely that you will misjudge whether or not testing is helpful, and when you do start needing tests, you're already not 100% sure what the exact semantics to test actually are. Since I believe that all except trivial one-off programs profit from unit tests, I consider the cost of expending effort on tests that are never run again to be negligible against the risks of extending untested and ill-understood code.

0
23

Some time ago I found a nice post: Why unit testing speeds up development. It can help you answer the question.

...What if the codebase... was provided with a substantial set of unit tests. A set that would say : “if all tests succeed, I guarantee that code still does what it should do” and if a test fails it exactly shows you where some behavior is broken . This is great, I could change the code to add things I want without wandering if the code still does what it should do, I just run the... tests and I have faith. This is a great world to be in as a software engineer. I noticed that I could advance way faster...

I have “faith”.

This is probably the most important reason why unit tests speed up development in a enterprise context.

I can trust that everything still works if all tests pass. If tests fail they will point out exactly where the problem lays...

...you have to have a high unit test coverage and good unit tests. When these conditions are respected you’ll find yourself in a situation that the effort for adding new functionality ‘s is almost independent of the size of the application and that in the long run it will speed up development.

Michael Feathers introduced in one of his books two ways of working with changes in code:

  • edit and pray,
  • cover and modify.

It does not matter how big is the code base.

20

According to Kent Beck in his answer to Stack Overflow question How deep are your unit tests?, you should test the code that you tend to get wrong.

If I don't typically make a kind of mistake (like setting the wrong variables in a constructor), I don't test for it.

4
  • 4
    Good point, and this implies that the OP's question is wrong; whether to test has nothing to do with the size of the project. A 5-line codebase may need tests, and a 1-line method in a large codebase may not (though other things in that codebase do). Commented Aug 8, 2012 at 16:36
  • This may work for tiny projects that you're working on alone, but for a project that is either done for work (where you don't control who will work on it in the future) or anything that may be open source, you need to test everything. And you need to start immediately because later it will be "too hard to backfill all the code that's already written"
    – xaxxon
    Commented Jan 12, 2013 at 17:53
  • @xaxxon: Kent actually talks about that in the same answer that Mansuro linked to, saying: "When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong."
    – henko
    Commented Jan 12, 2013 at 19:47
  • No, that's still incredibly short sighted. You cannot know who will be working on the code in the future. This is the type of mindset that afflicts junior developers.
    – xaxxon
    Commented Jan 13, 2013 at 3:21
5

Unit tests are implemented to save time and improve:

  • bug tracking
  • refactoring and/or re-writing code
  • integration testing
  • regression testing, etc.

It is a must to write unit tests for relatively complex parts of the program.

If you are sure that writing unit tests now will not save your time in future, you can skip it. However, you never know, and personally I can't think of a case when it is cheaper (in sense of time, money and nerves) not to write unit tests but do all the testing manually instead.

2
  • Generally a good answer, so +1. However, I think your final point misses the fact that you'll still want/need to manually test your unit tests! Commented Aug 8, 2012 at 9:16
  • @Baqueta, maybe I didn't sound clear, but I didn't mean say that unit tests completely replace the manual testing
    – superM
    Commented Aug 8, 2012 at 9:31
5

Unless you are going to write code without testing it, you are always going to incur the cost of testing.

The difference between having unit tests and not having them is the difference between the cost of writing the test and the cost of running it compared to the cost of testing by hand.

If the cost of writing a unit test is 2 minutes and the cost of running the unit test is practically 0, but the cost of manually testing the code is 1 minute, then you break even when you have run the test twice.


For many years I was under the misapprehension that I didn't have enough time to write unit tests for my code. When I did write tests, they were bloated, heavy things which only encouraged me to think that I should only ever write unit tests when I knew they were needed.

Recently I've been encouraged to use Test Driven Development and I found it to be a complete revelation. I'm now firmly convinced that I don't have the time not to write unit-tests.

In my experience, by developing with testing in mind you end up with cleaner interfaces, more focussed classes & modules and generally more SOLID, testable code.

Every time I work with legacy code which doesn't have unit tests and I have to manually test something, I keep thinking "this would be so much quicker if this code already had unit tests". Every time I have to try and add unit test functionality to code with high coupling, I keep thinking "this would be so much easier if it had been written in a de-coupled way".


TL;DR version:

Write a test when the cost of writing the test, plus the cost of running it as many times as you need to is likely to be less than the cost of manually testing it as many times as you need to.

Remember though that if you use TDD, the cost of writing tests is likely to come down as you get better at it, and unless the code is absolutely trivial, you will probably end up running your tests more often than you expect.

0
4

Test as soon as you observe regressions happen or fear causing some with your edits and not noticing.

Kindle that fear, let it grow to an adequate size: the sooner you test, the better.

Please note: depending on your role in the project, unit tests may not be the only kind of tests you want to write.

Everybody is rightfully obsessed with unit tests, because of bad mainstream testing practices in the past; but if you never tested before, you really should focus on testing in general, unit testing alone isn't going to solve world's problems.

3
  • 1
    I see you point but isnt't unit testing the basic starting point for startup programmers. And also could you elaborate more on what you mean by "testing in general". Thanks. Commented Aug 8, 2012 at 8:27
  • 1
    There are at least two other types of testing - integration test, and acceptance tests. Unit tests cover a specific unit (e.g. this function of this class is supposed to Frab the Fizz). You mock/stub all the other places where that class interacts, passing it el fake-o data. When you do integration tests, you combine two (or more) classes to make sure that your classes go together the way you think they should. Eventually you build up enough tests that you're doing end-to-end testing of your entire system, sometimes known as "smoke tests". Commented Aug 8, 2012 at 19:33
  • There's also regression testing tout court. Regression tests are usually bigger than unit test, may take a day to build, may imply access to test data and special test environments. Actually the unit tests are a smaller, a sleeker, and a more maintainable version of (old-style) regression tests.
    – ZJR
    Commented Aug 9, 2012 at 0:47
4

"Should I unit test this" can usually be answered by answering the following question: "Is it important that this function works properly, and is it important for me to know when it stops working?"

Of course, it's a lot more complicated than that, but that's a good way to start. Eventually you'll also weigh whether the code is already being tested by virtue of being used in another function, or whether your time would be better spent in another function, etc.

2

I believe that it's not the size of the project but the type of project which decides if it should use testing or not.

If you are working on a proof of concept, or on some other project where the goal is to learn from the coding, then testing is not required. If the project is meant to be used, maybe even sent into production, then it should be tested.

A quote from Robert C. Martin's "Clean Code": "If it's trivial to write, it's trivial to test", so there's no excuse to skip on the testing for short and trivial programs.

0

It really isn't a matter of size-- it's what you do with it (and how old it is). If I'm noodling around learning how a technology works and plan on throwing the thing away (we call this a spike in Scrum), I'll just code without doing much testing. If you are planning on developing it further (even if you are just noodling around), you should write tests around the code. TDD is a design technique even before it is a testing technique. You want to have a clear picture of what you want the code to do before you get bound up in the particulars of the execution. I would also NOT recommend trying to write extensive unit tests around large amounts of legacy code. Try to identify those parts that are complex (have a high cyclomatic complexity/spaghetti code feel to them) and those parts which fail frequently (they will often be the same). As others have suggested, I'd go read Kent Beck's book on TDD and definitely read Michael Feather's book. What they don't cover very much is the political aspect to writing unit tests around code. A lot of developers hate having to alter their code to make it testable, and a lot of developers do not feel the need to test code at all. It is something we have to work on as a profession. Every other engineering discipline is required to prove (often mathematically) that their work met the specification. We should do the same.

-1

Binding a Projects in limits of classes or functionality and then judging if this is suitable for unit testing may be wrong. There are numerous benefits of unit testing an application but real beauty starts when you have to maintain an application or have to work in distributed environment. So the choice comes here. Even a small change in your code can cause disasters.
I would not only suggest 'Unit Testing' but would also recommend to check your code coverage, ensuring maximum of your code is covered with Unit Test. Threshold for code coverage shall not be less than 95% and target must be around 100%. You can go for tools to track your code coverage and generate a report.
Visual Studio Provides Coverage Data - http://msdn.microsoft.com/en-us/library/ms182496(v=vs.80).aspx
Also you can use NCover or dotCover.

Not the answer you're looking for? Browse other questions tagged or ask your own question.