I'm currently looking for ways to improve the productivity of our team. I've read in a number of places that unit testing can be used to improve productivity. I can imagine writing unit tests now can be helpful in the future, but does it help in the short term too? Because I don't understand how writing more code (=more potential bugs) can help us meet deadlines.
Increasing productivity with unit testing
Also read Test Driven Development
Test-driven development (TDD) is a software development technique that uses short development iterations based on pre-written test cases that define desired improvements or new functions. Each iteration produces code necessary to pass that iteration's tests. Finally, the programmer or team refactors the code to accommodate changes. A key TDD concept is that preparing tests before coding facilitates rapid feedback changes. Note that test-driven development is a software design method, not merely a method of testing.
Unit testing is not about producing more lines of codes per day.
It is to ensure that every day, your new lines of code don't cause more bugs.
You need to be very careful about what you mesure when you try to evaluate your "productivity". It might help you meet your deadlines however, since you will spend less time fixing stuff.
It is not something aimed for the "short term" as in "we'll use unit testing and our next project will be done in 80% of the time".
Whilst a gross oversimplication, the sooner you catch a bug the less expensive it is to fix. As such, unit testing will at least capture some bugs up-front.
I suspect that in terms of productivity, it's a question of whether it's easier to fix a bug in code that's fresh in a programmers mind as opposed to a bug in code that's 'n' months old, etc. However, it's somewhat idealistic to presume that unit testing (outside of a larger testing regime) is some form of silver bullet.
How were you going to test without Unit Tests? By clicking around, visually checking answers? Is writing code once and running it many times a cost or a saving?
Were you going to exercise the various error conditions? Might you find the bugs later if you don't what are the relative costs of fixing bugs earlier rather than later?
However for me the most important reason is one that's less obvious: if you write the tests first (truly TDD) or even as you go you are almost lead into considering the fringe cases. And the result is that the code is just better. Less rework.
Another theory, humans are very goal oriented. We like rewards, and repeat behavious that give us rewards (mmm reputation mmmm ... give me a question to answer :-) seeing those little green ticks as our tests pass motivates us. You may get more code, but it gets written much quicker.
Not short term, but not long term either, having automated tests will allow you to detect problems (regressions) caused by wrong bug-fixing, or wrong-developments, faster ; and that is definitly nice.
It means when your application is in testing phase, each time a bug is corrected, you have less risk of introducing new ones.
And that is also true as long as the application is still in development : each time a developper commits a new module, you know it doesn't break the rest of the application (or, at least, that it doesn't break what is covered by automated tests)
And the sooner a bug is detected, the simpler and less costly it is to fix : if a bug doesn't have time to impact other developpers, it is way better too.
What if a developper considers some "bug" (which he doesn't know is a bug) as a feature and start relying on it ? What happens when this starts to be considered as a bug, and is fixed ? The other code breaks, I suppose :-(
Nice thing is also that developping automated-tests can mean more developpers know more about the code of the application : especially if some tests are developped / reviewed by other developpers than the ones who wrote the code in the first place.
Not sure it is "good pratice", but if done this way, it means there will be some kind of code-review in place -- and those are definitly helpful.
And as more developpers know the code, more developpers will be able to fix bugs in parts they did not develop initialy.
When you focus on writing tests close after or even before writing the real code you'll prevent yourself from writing too big chunks. When you have a lot of small tests then it's very likely that you structure your code so you're able to write these small tests.
This means that the classes don't need a lot of infrastructure to work etc. Things like dependency injection come in handy too because you may want to inject mock classes for your tests. This leads to more loosely coupled classes which will improve the overall code quality and make the code more maintainable. Additionally the safety-net of unittests will help you while the software evolves (and not only after the product is ready).
While coding most(aka all) people produce bugs. This leads to longer development of small features. If you write tests the probability for bugs decreases and if you find a bug you can be sure that your fix of the bug won't have sideaffects (if your test coverage of the "other" code is good). This saves a lot of time because you don't have to search for code that may be affected by the last change. This leads to a higher development speed after all.
Of course a developer needs to practise to write tests, but you'll get quicker pretty soon. Especially if you get used to libs that help you writing tests like easymock or something like that.
I can imagine writing unit tests now can be helpful in the future, but does it help in the short term too?
Yes, because you force your developers and architects to solve one problem at a time.
Because I don't understand how writing more code (=more potential bugs) can help us meet deadlines.
The amount of additional code is exactly the same. n lines of logic = n lines of tests. But as you know, the raw coding is not the part that takes more time, in particular because you can parallelize it very well. So writing more code is not the real issue. To meet deadlines you have to produce top quality code to be released, and without testing you have
- no way of knowing if the quality is top or not.
- no way of measuring when a release can be done. (when all tests passes as a first requisite)
Here are some thoughts. For my answer, I will define productivity as # of lines divided by number of bugs. If applied well, on average, I think unit tests will yield higher productivity.
Stuart Halloway uses the metaphor of double-ledger accounting: the test-code may seem redundant but having that other ledger is a huge payoff for getting a sense of quality.
With unit tests, the developer (or pair-programmer) is the first client of the software. This is why bugs are found more quickly, as others have noted. However, the person is also the first client of the OO model, API, etc. If a senior developer is involved (doing the work, or as a pair), the quality will improve from a design standpoint. This has mid and long term benefits. (This is often overlooked.)
Good unit tests will expose, and exercise, corner cases. These cases may not be reached via the vanilla tests that developers run manually. If you think about bugs found in the field: how many are due to some strange condition? In my experience, a lot.
It is true that, in the wrong hands, unit tests can feel like wheels spinning in the sand. But with some experience, the payoff is worth it, even in the short term. Yes, there may be fewer lines of production code but the bug rate will be much better.
"Test" is the wrong word with unit tests. "Defining behavior," is perhaps a better term.
Unit tests and TDD can improve productivity (even mid-term) in a number of ways.
- Code with well-defined behavior is easier to debug, as expected behavior is known.
- Code written with a TDD methodology tends to have crisper "seams", allowing for pieces of the codebase to be verified independently. This makes it easier to narrow down problems when they occur.
- Because of the strong test suite and well-defined behavior, refactoring becomes much, much easier. This allows design issues to be resolved with much less risk, even if they impact a number of individual classes.
- Because of the above, it's generally easier to determine, when something goes wrong, where the proper location for the fix actually is.
- Since TDD-written code tends to not rely upon singleton/static behavior or global state as much, less global behavior exists. With less global behavior, you get fewer side effects.
The biggest advantage, in my experience, of TDD-written code is the fact that it's well-defined. You start by defining what the code should do, and then making it do that. This contrasts with "regular" development practices which often involve writing a bunch of code, and then testing it to see what it actually does.
The other advantage of using a TDD-like methodology, is you get working code almost immediately, even if the end-to-end solution isn't in place. And it's almost always easier to add to working code to get more working code, rather than writing a bunch of code that's in an unknown state and then finding out what doesn't work correctly.
On short term I think unit tests don't help that much since it only reduces some testing time. The smaller the project the less the impact of this.
However the great thing about unit tests is that with writing them you can ensure that a specific kind of error you have coded against will always be detected. For long term they're a must have, for mid term I would recommend them.
And on the short term they will probably decrease productivity but if the project itself isn't short term you're bound to benefit from them.
If you by short term mean a month or two I think the answer is yes. How? When I need to make changes to my own code that I haven't touched for perhaps just a few weeks, or to code that somebody else in the team wrote, I feel a lot more confident if there are unit tests and the code coverage is good. If there were no tests I would be more inclined to patch, work-around and generally avoid touching the main algorithm. Do that a couple of times and the code becomes incomprehensible.
Scenario: Project meeting
Product owner: "We need to make a change to X and add the Y feature. Is it doable?".
Team: "It would be better to wait for Joe to come back. He wrote that code."
A few weeks later..
Joe: "Sure, it can be done but considering all the testing that went into that module it's not a quick fix".
Product owner: "Oh. So.. let's postpone that change for while..."
I'm not sure whether I'm answering your question. It really depends on how short the short term is. ;-)
Unit testing improves short term productivity in the following sense: It makes it more likely that your code solves the right problem earlier. Spending neuron cycles on creating tests will make the programmer think about the different use cases and the user interface (or API) of that code.
The opposite scenario would be to code away for a couple of weeks and only then realize that the code solves half of the problem. Now you have to patch your code, or perhaps even throw it away and start over.
How does unit testing improve productivity?
The implicit assumption in this question is that unit testing does improve 'productivity'. If we define productivity as producing a perfect deliverable for a given effort in man-hours then being more productive can be interpreted as producing that deliverable in less than the given effort. If a coder produces 'perfect' code straight-off then doing unit testing will decrease productivity.
Testing is not primarily for improving productivity, it is for validating and verifying software entities in the sense that you are checking the right product is built and that the right product is built correctly. Creating tests and running them does have side-effects, the most important one being that of making the software creators understand the problem that they are trying to solve with software.