Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question

closed as primarily opinion-based by Evan Plaice, GlenH7, MichaelT, Bart van Ingen Schenau, jwenting Feb 28 at 9:03

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.If this question can be reworded to fit the rules in the help center, please edit the question.

25  
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". –  Amos M. Carpenter Aug 8 '12 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. –  Emmad Kareem Aug 8 '12 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. –  Lamin Sanneh Aug 8 '12 at 8:51
    
unit testing is not for development but for maintenance... –  user1249 Aug 8 '12 at 9:25
12  
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. –  Wonko the Sane Aug 8 '12 at 12:06

12 Answers 12

up vote 197 down vote accepted

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());
        }
    }
share|improve this answer
5  
+1 for nice practical approach. –  asdasd Aug 8 '12 at 10:10
21  
Surely you should start earlier, at the 0 class/0 function point... if you're following TDD :) –  Kaz Dragon Aug 8 '12 at 12:52
101  
+1. If you program is big enough to have bugs, it's big enough to have unit tests. –  Jason Orendorff Aug 8 '12 at 14:03
6  
@JasonOrendorff: I'm mocking that up into a poster and putting it in my office. Brilliant. –  Justin ᚅᚔᚈᚄᚒᚔ Aug 8 '12 at 14:50
6  
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 Aug 8 '12 at 21:26

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.

share|improve this answer
7  
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 Aug 8 '12 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. –  Wayne Werner Aug 8 '12 at 11:44
8  
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(). –  Dan Neely Aug 8 '12 at 12:30
3  
Uh, I think you missed one: "Making sure the code works the way it's supposed to!" –  BlueRaja - Danny Pflughoeft Aug 8 '12 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!" –  Baqueta Aug 9 '12 at 15:53

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.

share|improve this answer
21  
Programmers are notoriously bad at judging their own skill of predicting the future –  superM Aug 8 '12 at 8:53
3  
@superM I agree with you. The "run once and throw away" program I already wrote during my short career all stayed, were ran every few days, and became business-critical. I call that the "temporarmanent" aka the temporary-permanent effect.... sigh –  Jalayn Aug 8 '12 at 11:20

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.

share|improve this answer

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.

share|improve this answer
3  
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). –  Nathan Long Aug 8 '12 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 Jan 12 '13 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 Jan 12 '13 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 Jan 13 '13 at 3:21

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.

share|improve this answer
    
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! –  Baqueta Aug 8 '12 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 Aug 8 '12 at 9:31

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.

share|improve this answer

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.

share|improve this answer
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. –  Lamin Sanneh Aug 8 '12 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". –  Wayne Werner Aug 8 '12 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 Aug 9 '12 at 0:47

"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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

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