Click here to Skip to main content
Click here to Skip to main content

The benefits of automated unit testing

By , 8 Nov 2003
 

Introduction

Writing software is very difficult. Writing bug-free software all the time is virtually impossible. There are many reasons why this is so; anyone who has written an untrivial piece of software knows how easily a human can miss a tiny detail, and how the slightest of omissions can cause a most spectacular crash, most likely at the most awkward moment.

Unfortunately, the task of writing software promises to be no easier in the future. While software technologies do advance, so does the complexity of the software we write. There is no magical trick in sight in the foreseeable future that would make writing bug-free software simple and straightforward. Still, not all hope is lost - there are some things we can do to substantially improve the quality of software we write.

Ad-hoc Testing

The development of new features to a software product goes in phases. No matter what the methodology, the developer usually starts with the requirements, proceeds to design, then writes the code, debugs it, and finally checks the code into the source code version control system. At this point, the feature is considered done. But how does the developer know that the code actually works?

In many smaller companies and companies that are not really software houses but still develop software for their own use, the developer spends a day or so testing the feature, simply running the application and trying out the functionality with different inputs while observing that the outputs come out as designed. After having completed this testing, the developer has some confidence in that the code works the way it is supposed to. But every developer who has ever written code to an actual product knows the nagging feeling of uncertainty. How good a coverage did the testing have? Did I test every single feature in the application – otherwise how can I be sure that the new code did not accidentally break some other, apparently unrelated, piece of functionality? What if new code written by somebody else two weeks later will adversely affect this feature?

Using developer time for manual ad hoc testing is not a cost effective way of ensuring software quality. Developer time is expensive and is better spent on writing software rather than test-running it ad nauseum. This kind of testing finds out whether the new code affected some other piece of functionality only if the developer tests every single feature in the application. Further, it gives no guarantee whatsoever that the feature still works two months down the road as more features have been added to the system.

Quality Assurance

Some companies have a more or less formal quality assurance process with a team dedicated for testing. The team may have test case scripts that the team goes through and manually tests the software. This activity is carried out after every internal release of the software. Customers will see a new version of the software only after the tests pass and the QA team leader has signed it off.

This kind of testing is better than ad-hoc testing but it is far from optimal. Human testers can and will make mistakes. While hired tester time is cheaper than developer time, the cheapness is offset by the fact that the problems are uncovered relatively late in the development cycle. Every time QA acceptance tests fail, the developers get notified; they fix the problems and give a new version of the software to QA. Time and energy is wasted on communication while the software bounces back and forth between the developers and the QA team. In addition to wasted time and energy, this trashing can have side effects such as creating a ‘ghetto’ mentality in QA personnel.

Quality assurance teams may also have automated testing systems. This is more effective than manual testing, but still is not the optimal situation. Test scripting systems tend to be expensive. Writing good test scripts and maintaining them is something that a tester who was hired for a summer job is not likely able to do. Hiring someone who can write and maintain tests will likely cost as much as hiring a developer in the first place.

Automated Unit Tests

I am not going to describe how to write unit tests in this article. There are already articles on this site that can get you started. Suffice it to say that writing cost effective unit tests is not trivial. It is just like writing any other type of software: it takes time, effort and skill. For now, I’m just going to take the easy way out and list some very basic guidelines for writing and running unit tests.

A unit test is a piece of code that exercises another piece of code. There are essentially two flavors of unit tests: point unit tests exercise a small piece of functionality, e.g., just one method or methods of a class. End-to-end tests exercise one feature across many, sometimes all, layers of an application. An ideal end-to-end test works like an end user story: "the user logs in, invokes the monthly revenue report, sets the date range of the report from July 1st to July 31st, runs the report and observes that all the numbers come up as expected and add up". This is a fairly liberal definition of a unit test; for the purposes of this article anything that you would write e.g., as a NUnit test case is a unit test.

When implementing a feature, a developer should write the code together with a unit test that ensures that the feature actually works. In practice this means writing code that e.g., calls an entry point method of the feature and then verifies that the code did what it was supposed to. For example, if you have a method which transfers money from one account to another, the unit test would call that method with accounts with known balances and then verify that the balances come out the way they are expected to.

When the feature and the unit tests are complete, the developer checks in the source code - including the unit test code - to the source version control system. It is vital that the unit test code is checked in to the version control too. This allows integrating the unit tests with the build. It also allows other developers to check out the unit tests on their local machines and run them at will.

As a rule, before a developer checks in any code into the main source control repository, she should get the latest versions of the unit tests from the version control on her development machine and run all the tests locally. Only after all unit tests pass should the developer check in new code. This ensures that the source code in the version control system remains healthy at all times and can be used to rebuild the system at any time.

In order to get the full benefit from unit tests, the test suite should be run as part of the build process – this is what I mean by ‘automated’ unit tests. The build along with the unit tests should be scheduled to run automatically once or twice a day. If you have unit tests but do not run them as part of a scheduled build, then you are not getting the full benefit from the tests. By running the tests as part of a scheduled build, you test early and often. This again ensures that the source code in the main repository remains healthy. In real life, developers may accidentally check in code that does not work. The daily build should be your main line of defense against these bugs. There are some wonderful and cheap tools for implementing build and test systems, e.g., if you are developing for .NET, you can use NAnt and NUnit frameworks. How to implement a build process is again a fairly large topic and resources on this site and elsewhere on the web can get you started.

Writing unit tests is an extra effort if compared to not writing tests at all, and this should not be ignored. In my experience writing unit tests adds roughly 10-30% to the time it takes to complete a feature. End-to-end tests tend to be the most time consuming type of tests to write. Then again, when writing end-to-end tests one usually very quickly creates a small framework as the common code in the tests is factored out. Thus writing end-to-end tests comes easier after the first few test cases have been written.

Both types of tests - end-to-end and point tests – are needed for best coverage. End-to-end tests find different kinds of problems as they exercise a number of components that participate in the implementation of a feature. Point unit tests are also needed for the most important components because they can verify the functionality of a component more thoroughly.

Benefits of an Automated Unit Test Suite

An automated unit test suite brings along a number of important, tangible advantages as compared to other testing strategies.

First, unit tests find problems early in the development cycle. The common wisdom in software development is that the earlier problems are found, the cheaper it is to fix them. An automated unit test suite finds problems effectively as early as possible, long before the software reaches a customer, and even before it reaches the QA team. Most of the problems in new code are already uncovered before the developer checks the code into source control.

Second, an automated unit test suite watches over your code in two dimensions: time and space. It watches over your code in the time dimension because once you’ve written a unit test, it guarantees that the code you wrote works now and in the future. It watches over your code in space dimension because unit tests written for other features guarantee that your new code did not break them; likewise it guarantees that code written for other features does not adversely affect the code you wrote for this feature.

Third, developers will be less afraid to change existing code. Over time, software systems become more and more change resistant because developers are reluctant to change old code. This is natural because when changing old code, there is always the risk of breaking it or some other part of the system through a side-effect.

The fear of changing code is bad because in one respect software is just like any other physical system: it is subject to the law of entropy. Over time, as new features are added and bugs are fixed, the overall quality of the code degrades. This is even more so if the software is successful since there will be pressure to add new features which do not quite fit into the original architecture. No practical architecture can be designed to accommodate every thinkable feature, and in the changing world there is no way we can foresee all future requirements anyway. The only way to keep adding new features to software and retain the internal quality and clean design over time is by way of refactoring. Without occasional refactoring, the code grows more and more internally tangled until every class knows of every other class. Refactoring and cleaning up existing code is a really scary thing - unless you have automated unit tests.

Fourth, the development process becomes more flexible. Sometimes it may be necessary to fix a problem and to deploy the fix quickly. Despite best efforts, a bug may slip in and an important feature may stop working. The customers cannot purchase products, the users cannot work and your boss is breathing over your shoulder asking you to fix the problem immediately. Releasing quick fixes makes us feel uneasy because we are not certain what side-effects the changes might have. Running the unit tests with the fixes applied saves the day as they should reveal undesirable side-effects. Publishing hotfixes is something we hope we never have to do, and a unit test suite should already decrease the need for such things anyway. But if you ever have to publish a hotfix, a unit test suite improves your chances of doing so without introducing new problems.

Fifth, having a unit test suite improves your project’s truck factor. Truck factor is the minimum number of developers that if hit by a truck the project would grind to a halt. If you have one key developer who works on a subsystem that no-one else knows, then your truck factor is effectively “1”. Obviously, having truck factor of “1” is a risk on the project.

A comprehensive unit test suite improves truck factor because it makes it easier for a developer to take over a piece of code she is not intimately familiar with. A developer can start working on code written by others because the unit tests will guide the developer by pointing it out if she makes an error. Losing a key developer for any reason just before a release is less of a catastrophe if you have the safety net of unit tests.

Sixth, an automated unit test suite reduces the need for manual testing. Some manual testing will always be needed because humans excel at discovering bugs that involve complex data and workflow processes. Writing a unit test for the most complex cases might be so prohibitively time consuming that it is not cost effective any more. The QA team can concentrate discovering the hard-to-find bugs while the unit tests do most of the mundane testing.

The net effect of the benefits listed above is that software development will become more predictable and repeatable – in a word, a bit more like a real engineering discipline. The design and coding phases still have a fair amount of ‘art’ in them, and this will not go away. Once the coding is done, the build process builds and tests the software much like physical products are built on an assembly line. This removes much of the ad-hoc nature in software development which is the underlying reason for many of the problems that plague software projects.

The Future

In addition to the immediate and tangible benefits listed in the previous section, I foresee a future in which unit tests will help in answering to change pressures from two directions. At this point, I would like to point out that the following discussion applies to different kinds of software in varying degrees – it applies best to business software and applications, e.g., CRM, ERP and such. I do not see similar major changes taking place in the development of operating systems, device drivers, database management systems etc.

The raison d’être of a software developer, and thus that of a software company, is to make the buyers and users of the software happy. In more precise terms, the developer should provide the end user with software that corresponds to the user’s real data processing needs in a reliable and predictable manner. This is a very difficult task to carry out and traditionally we software developers have not been very good at it.

I have seen an organization where developers became so frustrated with the end users’ constantly changing requirements that in the end they had the end users’ representative sign off the requirements document before they started to work on the implementation. Later, when the users complained that the software does not address their actual needs, the developers showed them the document: “look, this is what you signed off, and that is exactly what was implemented”. The developers got their moral victory but in the end both the developers and the users lost.

The way for both to win is to start by recognizing the fact that the world is constantly changing. A company’s business needs are always changing and a company that does not adapt will eventually die. To address this, we need to start developing software with what I would like to call Extreme Customer Oriented Rapid Application Development (E-CORAD). The end user’s software will be a smart client with pluggable modules that can be updated independently. The developers will release a module early in the development cycle so an end-user dedicated for this task can try it out; the user will give constant feedback to developers allowing them to refine the module through frequent and small incremental releases. This method of development guarantees that the final product will correspond to end users’ real needs. Automated unit tests will be the major enabler that will allow this cycle to take place frequently without generating chaos. CORAD as such is not a new invention but technological advances such as .NET combined with unit tests will allow us to take it to new extremes.

There are certainly plenty of technical and non-technical challenges in E-CORAD but I do believe the challenges are solvable.

The second direction from which there will be pressure to change the way we develop software is that of service-oriented architectures (SOA). Smart clients will pair with loosely coupled, service-oriented architectures on server side (how’s this for buzzwords in one sentence?). These new architectures will fundamentally change the way we design, develop, deploy and maintain software. Client and server side software will be developed and deployed independently from each other, using abstract contracts as points of contact. Loose coupling translates in practice to less type safety, and thus we will have less help from the compiler in catching those stupid and simple mistakes we make all the time. All this flexibility will result in utter chaos unless we do serious automated testing. A unit test can exercise a Web Service to ensure that it abides to its contract. A unit test can test a Web Service consumer by having it consume mock services that return predefined data.

We need automated unit tests in order to realize the promises of SOA. Also, with SOA, software needs to be highly adaptable, and that again means we will develop software in a frequently occurring cycle of small, incremental releases. This is only possible if we have the automatic assembly line with unit tests that will allow the cycle to take place often without compromising system integrity.

From these changes will emerge a ‘Brave New World’ of software; this is a topic on which I hope to write another article soon.

Unit Testing in the Real World

Despite all the benefits automated unit tests bring us, it has to be said that they are not the silver bullet that will rid us from buggy software for good. Trusting unit tests blindly as in: "if unit tests pass, code is ready for production" is a recipe for shipping bugs. Even if we have a comprehensive unit test suite that is run frequently, bugs can still sneak in and some amount of manual testing by humans is needed.

When a bug makes it into production despite a unit test suite, we need to do post mortem analysis. Whenever this happened in the projects I’ve worked in, one of the following things turned out to be true:

  • There were two bugs in the code: the original bug in the application code and another one in the test code. Usually when this happens, it is due to special circumstances in the code being tested. For example, in a web application project I worked on, there was a feature that allowed the user to reset her user account password without logging in. The unit test framework performed a login automatically in the beginning of each test case, which made perfect sense for 99% of the tests. For this particular feature, the automatic login hid a bug that manifested itself only when the user was not logged in. The "reset password" unit test ran happily while the actual feature failed miserably after I added some code that as a side-effect required the user to be logged in. The moral of the story is that while bugs may still creep into production code, it will take two bugs instead of one. The chances for the two bugs occurring together are slimmer than for the first bug occurring alone.
  • The production environment is different from the test environment. For example, in the same web application mentioned above, there was a different version of a database driver in the production system than in the test environment. A bug in a query that produced seemingly sensible results in the test environment generated a syntax error in production. The obvious conclusion is that the test environment should reflect the real environment as closely as possible.
  • The third possibility of course is that the feature in question did not have a unit test to begin with. This is an open invitation for bugs to come in and crash the party. Even the simplest smoke test that does basic verification is usually worth writing.

Every time a bug makes it into production, we go back to the unit tests and add a test case to specifically verify that this bug never occurs again. This way the noose gets tighter and tighter on bugs and it becomes more and more difficult for the bugs to slip through.

There are developers who think that writing unit tests is not worth the time and effort. Sometimes this objection is due to the fact that the developers equate unit tests with micro unit tests, e.g., unit tests that exercise a single get/set property of a class. Writing tests that test trivial code is not worth the time spent. It is more cost effective to write a test that tests a piece of functionality that would fail if the property did not work properly. As a side-note, with .NET it is so easy to write a generic test that tests get/set properties of a given class through reflection that it actually makes sense to write it once and have it do the trivial tests. Another typical objection is that writing more advanced unit tests requires skill, takes time and can be boring. To this I can only say that the unit test should be considered an integral part of a feature, and writing effective unit tests is like writing any kind of software: it requires skill and expertise.

The downside of having a unit test suite is that it needs to be maintained. If interfaces in application code change, unit tests that exercise the code will break. There is no easy solution to this issue other than convincing the reader that the benefits of the tests outweigh the extra effort in developing and maintaining the tests.

Summary

The recipe for better software with less people is simple: unit test early, unit test often, and refactor when needed. Unit tests find problems automatically, early and will never grow tired of testing the same feature again and again.

A comprehensive unit test suite that runs together with the daily build is the heart beat of a software project. It gives a sense of progress and stability. Email notifications of successful builds with unit tests can boost project morale. An email notification of a unit test failure, on the other hand, tells all project developers where they should focus their attention to in order to get the problem fixed.

Despite all the benefits that unit tests bring, some amount of manual ad-hoc testing is still needed. The developer needs to run the application and use her best judgment to see if the code really does what it is supposed to. A dedicated QA team is also needed in bigger projects. But with a carefully written unit test suite, the software is self-testing and the need for manual testing and separate QA personnel will be reduced. The benefits of automatic unit tests do outweigh the extra time and effort in writing and maintaining the tests.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Sami Vaaraniemi
Web Developer
Finland Finland
Member
Sami Vaaraniemi has been working as a software developer since 1990, primarily on Microsoft technologies. After 12 years of Win32 API and C++ he switched to .NET. He currently works as an independent consultant and can be contacted through his website at www.capehill.net.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralUnit Test Softwaremembergjr8 Aug '04 - 21:19 
Any recommendations for simple, effective, unit test software for the C++/MFC/Visual Studio environment?
 
gjr
GeneralRe: Unit Test Softwarememberana_v12324 Aug '05 - 14:04 
Any one interested - have a look at www.testingfaqs.org/t-unit.html
 
Ana
GeneralRe: Unit Test SoftwarememberAl Einstien15 Sep '05 - 18:41 
NUnit[^]
GeneralRe: Unit Test SoftwarememberChris Cole20 Oct '05 - 12:37 
I prefer csUnit. Although NUnit is more popular, csUnit has superior IDE integration.
 
----------------------
Chris Cole
QuestionWhat is quality assurance?memberAndrew Phillips10 Nov '03 - 15:20 
I like your article and I believe that automated unit testing is an important part of creating better software.
 
What I do object to is your use of the term "quality assurance" to describe a post-inspection process. This form of testing has nothing to do with assruing quality. In manufacturing industries it has been recognised since the time of Henry Ford that inspection of a product after it has been created will not find all or even most defects. In software this is far worse since the permutations and the ways software can fail are much greater. A testing team should at best be called a "quality control team".
 
The fundamental aspect of quality is that it must be built in, it cannot be added later. It is everyone's responsibility which cannot be handed off to a QA team. (This is not to say that I think that acceptance testing should be eliminated altogether.Smile | :)

 
Andrew Phillips
aphillips @ expertcomsoft.com
GeneralTest First DevelopmentmemberArjan Einbu10 Nov '03 - 9:28 
I'd like to emphasise the Test First Development concept, in which one must always create a failing test. (If a test never has failed. It's not worth anything.)
 
Best way of making sure a test will fail, is creating the test first, before developing the code that solves a problem.
 
A failing test is proof that test is actually running and testing anything at all, and only then can the unittest be seen as a verification or proof of that the method beeing tested is really doing its job.
 
When the test is created upfront, you don't know the exact implementation details of the solution you are testing. You only know how it is supposed to behave. (Either since you know the output from a method, the state of an object or the exceptions it should throw.) This is a good thing!
 
After the test has failed atleast once (with the empty solution) you can start programming on the solution. When the tests work, your solution is done. (Or you start creating more test for new functionality. Next iteration of the project.)
 
XP, or eXtreme Programming, uses the Test First approach to development.
 

Have a look at my latest article about Object Prevalence with Bamboo Prevalence.
GeneralRe: Test First DevelopmenteditorMarc Clifton10 Nov '03 - 11:15 
Arjan Einbu wrote:
When the tests work, your solution is done.
 
Really? What if your unit tests omit:
 
1) how the test function handles incorrect data (some examplesSmile | :)
a. alpha chars where there should be none
b. double decimal points
c. negative sign where for positive only values
d. range validation
e. selection list actually selected
f. state integrity (if checkbox A is checked, then item B is valid only under condition Y)
2) the network connection failing
3) memory leaks
4) excessive memory/resource utilization
5) poor performance
6) thread lock (not handling timeouts)
7) rounding/truncating problems
8) performance under stress tests
9) user doing something out of the expected sequence
10) state transitions
etc., etc., etc.
 
If the unit tests pass, all that you can conclude is that the unit tests pass. How people make the conclusion that the "solution is done" is a leap of logic that is beyond me.
 
Iterations and refactoring? Riiiight. The application is still buggy, the bugs may be found in the acceptance testing, and the customer is left wondering, why I am I finding bugs when I was told this crap was unit tested?
 
If your code is:
 
A->B
 
your unit test only tests that given A, then B.
 
The situation,
 
{*}->B' (given any condition, then B handles it gracefully)
 
is impossible to test, because the set of tests is infinite. But let's be reasonable.
 
Given B, there is a set of T tests that are reasonable to test. What are the rules that you can use to help quantify {T} so that {T}->B'?
 
That is the $64K question that nobody seems to be able to answer. And I firmly believe that, if someone really applied themselves to the problem, a good set of rules could be established. Only then will I believe that the set of unit tests truly reduces the bugs in my application.
 
Now, let's look at "reasonable to test". Reasonable to test is qualified by:
 
project budget
project time
people resources
analysis of the function B to determine T
complexity of the test (development/debugging time/cost)
long term benefit of the test
 
This is multidimensional domain in which we have to determine that the unit test is reasonable, and each of these factors has a different weighting. I think this kind of analysis is doable, but I also think that this detracts from lightweight methodologies like XP, which specifically try to avoid too much design/analysis.
 
A Catch-22.
 
Marc
 
Latest AAL Article
My blog
Join my forum!
GeneralRe: Test First DevelopmentmemberChris Tavares10 Nov '03 - 13:46 
Unit testing is a development activity, NOT a testing activity.
 
What does that mean? The goal of unit testing is not "testing": finding the bugs in the code.
 
Instead, unit testing (in the test-driven development theory) is there as a tool to figure out how the functionality should be designed. I almost prefer to look at my test cases not as tests, but as experiments, and example code that I can easily re-run.
 
The tests get kept around so that, as you do refactoring later, you make sure you haven't changed something that you depended on.
 
Unit testing is not the be-all-end-all of testing, and it in no way replaces a QA department.

GeneralRe: Test First DevelopmenteditorMarc Clifton10 Nov '03 - 14:06 
Chris Tavares wrote:
Unit testing is a development activity, NOT a testing activity.
 
OK, that's a good point. Thanks for changing my perspective on that. But, are you saying that unit tests are another design tool? How is it a better design tool than formal design practices?
 
Chris Tavares wrote:
you make sure you haven't changed something that you depended on.
 
OK. This is the one thing that I can grasp. But personally, I feel that more can be gained from a good framework. In my experience, a significant amount of the refactoring is eliminated when changes are made in an application that uses such a framework.
 
Marc
 
Latest AAL Article
My blog
Join my forum!
GeneralRe: Test First DevelopmentmemberChris Tavares11 Nov '03 - 7:31 
Marc Clifton wrote:
OK, that's a good point. Thanks for changing my perspective on that. But, are you saying that unit tests are another design tool? How is it a better design tool than formal design practices?
 
Yep, that's exactly what I'm saying: in my mind, unit tests are primarily a design tool.
 
As for how it's better: my experience with formal design techniques comes from having worked on military projects. We would spend literally months of time crunching models, doing analysis, exhaustively looking at alternatives, and in the end... we had a stack of paper and no code. And to top it off, we STILL got the design wrong more often than not.
 
With test-driven development, you start with your basic functional requirements, and you build your design through a series of tests. The tests drive your API, and as you find corner cases you build more tests.
 
In the end, you have working code, and not a giant stack of paper. And even better, with the test suite available, I'm not afraid to change things when I find that I've made a mistake, because I don't have those "what else will this change" problems you do without the test suite.
 
It may not be better, but it's no worse, and a lot more satisfying way to work than the reams of paper I used to have to produce.
 
Marc Clifton wrote:
OK. This is the one thing that I can grasp. But personally, I feel that more can be gained from a good framework. In my experience, a significant amount of the refactoring is eliminated when changes are made in an application that uses such a framework.
 
In my experience, the best frameworks evolve rather than being done up front. If you're doing essentially the same job for the fourth time, absolutely you should have a framework. The first time you do a job, it's too early to be thinking frameworks. Start simple. The framework will reveal itself over time.

GeneralRe: Test First DevelopmentmemberArjan Einbu10 Nov '03 - 21:25 
Arjan Einbu wrote:
When the tests work, your solution is done.
Marc Clifton wrote:
How people make the conclusion that the "solution is done" is a leap of logic that is beyond me.
 
You're right. It is unreasonable to believe that one writes test so much better than one writes application code. But still, as a mechanism to determine when to move on to the next piece of code we need to make, test-first development makes good sence.
The main ideas behind test-first, is that you know your tests have been run. The tests will show you that by failing at least once. It answers the question: "how can you be sure it tested anything at all?"
 
If you want to use unittesting (for numerous reasons mentioned in the article) you need to have some tests. Test-first is a good way of making sure at least a few tests exist for all functionality.
There will be more bugs to fix, and when other sorts of testing show that you have a bug, then use the test-first approach to write a test that will demonstrate that bug. THEN go on to fix it. This way your test suite matures. It will be more complete for every new test added, and each test ensures that you dont re-introduce bugs you have removed before. (Or goes a long way in ensuring that you dont introduce new bugs in previously tested functionality.)
 
I dont think unittests can be said to be more complete than matured code, but they can help you reach it safely.
 

 

Have a look at my latest article about Object Prevalence with Bamboo Prevalence.
GeneralWow!memberJeff Varszegi9 Nov '03 - 18:08 
Sami,
 
This is one of the best-written articles I've seen on this site. Your article doesn't have flashy multicolored graphics, but it is just fantastic: unrepetitive, compact and to the point. (Maybe you should add some flashy multicolored graphics to lure in the magpie types! Just kidding.) Thanks a lot for the nice read. I agree with absolutely everything you have to say, and I'm glad to be the second to vote 5 for this stunningly crafted article.
 
Regards,
 
Jeff Varszegi
GeneralRe: Wow!memberSami Vaaraniemi10 Nov '03 - 5:52 
Thanks, I was a bit worried that the article would be disqualified as, just like you said, it has no pictures and what's even worse, there's no code at all. I guess my next article is going to have to be all code and pictures.
 
Sami
GeneralNo easy solution.memberWREY9 Nov '03 - 15:43 
There is no denying that the software development industry is broken, and is DESPERATELY in need of fixing. But if one wants to confront the problem, and stare at it straight in the face (without being hypocritcal about a LOT of what's behind the cause), I will step forward and say, "MUCH of the problem plaguing the software development industry has to do with a good many of the people we think of as programmers, but who in reality are nothing but HACKERS!!!"
 
I am sick and tired of going into projects and looking at the work done before by these people, and find myself getting angrier by the minute with the code I'd see before me. Little wonder why the customer is having technical problems with their system (which have rippling effects in other areas of the company). The quality of the work is so hideous, many times I would go right back to the client and inform them, that before I can start doing any meaningful work, I'd need a day (or two) to clean up some of the garbage I see in the current code. With that, I would also accompany such statements that I would NOT be charging them for the time spent cleaning up the code.
 
OK! So I give up a day or two of making money, but the gains for me in other ways, are tremendous, including making the customer feel I am more interested in the well-being of their company than in my own personal financial gains.
 
For me, it also offers the improved opportunity that starting off with cleaner code will more likely result in a better outcome as far as having a clearer view of what I'll be changing and doing.
 
Yes, I've also had indifferences expressed when I'd offer to clean up the code without charging for it, due to some earlier HACKERS who had made the same offer (to get themselves in grace with the client), but ended up creating new problems of their own.
 
The common fiber that runs through most (if not all) of these experiences, is the careless, shoddy, and third class quality work done by those camouflaging as programmers. These people go into a project and write some very poorly designed code, which because it works in some instances (called "unit testing", and because they are good political players) get their work accepted, until the users starts getting fed-up with the many broken and unreliable performances of their system.
 
It is tragic that these bad apples still somehow manage to find work to do, and you know they have been at someplace before by what they leave in their wake. They are the primary cause and justification for "Automated Unit Testing", and if nothing else, I would be pleased to see "Automated Unit Testing" becoming commonplace just to stop these people dead in their tracks, revealing them for whom they really are: HACKERS.
 
Mad | :mad:
 
William
 
Fortes in fide et opere!
GeneralRe: No easy solution.editorMarc Clifton10 Nov '03 - 1:58 
WREY wrote:
It is tragic that these bad apples still somehow manage to find work to do, and you know they have been at someplace before by what they leave in their wake. They are the primary cause and justification for "Automated Unit Testing", and if nothing else, I would be pleased to see "Automated Unit Testing" becoming commonplace just to stop these people dead in their tracks, revealing them for whom they really are: HACKERS.
 
The one fallacy in this is that the very same hackers would be writing the unit tests, which would of course be equally worthless. Once you got hold of their code and wrote real unit tests, everything would start breaking and you'd be back to where you started--cleaning up crappy code.
 
This is my problem with unit testing--it's only as good as they guy writing the tests. And having also seen what you describe, I have no faith that most so called programmers can write good unit tests.
 
Marc
 
Latest AAL Article
My blog
Join my forum!
GeneralRe: No easy solution.memberRanjan Banerji10 Nov '03 - 4:59 
I think writing unit tests is not any different from writing code. It takes time to get used to and it requires constant refactoring when you get started. But once you get the hang of it, its a life saver.
 
As far as bad code/unit tests is concerned. It will never cease to exist. Specially in the consulting world. For various reasons such as:
 
1. Pressure to deliver very fast
2. Low budgets (your coompnay bids too low just so that it gets the contract)
3. Bad developers (code and design)
4. Bad management
5. Changing contractors (one year the work is done by consulting firm "A" the next by "B"). "B" focusses on blaming "A" rather than doing work. "A" of course screwed up for various reasons including those listed above and the cycle never ends...
 
I guess there are a billion other reasons but these come to mind based on my experience. So its not always bad developers Smile | :)

GeneralRe: No easy solution.editorMarc Clifton10 Nov '03 - 10:46 
Ranjan Banerji wrote:
I think writing unit tests is not any different from writing code. It takes time to get used to and it requires constant refactoring when you get started. But once you get the hang of it, its a life saver.
 
But there's the problem. Everyone says it takes experience. I think the real conclusion to draw from this is that inexperienced programmers should:
 
1) be apprentices, working with a "master"
2) not be allowed to contribute to production code until...
3) they have "mastered" the skill--demonstrated their ability by writing their own "product".
 
Ranjan Banerji wrote:
As far as bad code/unit tests is concerned. It will never cease to exist.
 
I would hope that someday writing bad code is a thing of the past. But unit testing is not the solution.
 
Ranjan Banerji wrote:
So its not always bad developers
 
Agreed.
 
Marc
 
Latest AAL Article
My blog
Join my forum!
GeneralRe: No easy solution.memberJon Rista8 May '06 - 10:50 
I have to agree about #4, Bad Management. I fully agree that there are many programmers, actually probably the majority of programmers, who are hacks or fonies and don't have any real skill. But thats only the beginning of the problem. It is entirely possible for a good programmer (or a team of good programmers) to be pulled down by bad management.
 
I have had several bad experiences over the last 2 years and some, but not due to the poor quality of my fellow developers. I havn't had what I could call a "successful" project in almost all of those 2 years, and the primary cause was bad management. Underbidding, overpromising, overconstraining time and resources, etc. When a project's lead/senior developer doesn't have the time, resources, and manpower to pull off what has been promised, but delivery is an absolute, then the inevitable consequence is that corners will be cut. Usually, the first thing that has been cut in projects I've worked on the last couple years was unit testing, and after that, time spent designing and planning.
 
Once you have cut out adequate design time and testing, the only thing left is coding. Lacking a map and the safety net of unit tests, projects quickly get out of hand. Code becomes spaghetti mush, people on the project may change, and manual testing by both the developers/qa team and the client increases. Funds, which are now needed more than ever, becomes even scarcer as the client picks up on the situation and the quality of the product they are getting.
 
The kicker is, all of this is due to poor management and additional pressure on the developers, who do what they have to to deliver. So the problem is grander than just having a world full of hack programmers who have no passion and talent for their job. Quality management is as essential to being able to deliver a solid product as quality develeopers and quality testing.
GeneralRe: No easy solution.memberSami Vaaraniemi10 Nov '03 - 5:35 
I've seen the guys you describe too. Usually they code at most a year or so and then move on to... project management.
 
Seriously though, if you don't trust your fellow developers then that is a real problem. One thing you could do is to review their code. That of course does not help much if you get to see their code only after the product has shipped. Also, code review is a two-edged sword as some people take it personally. In one project I worked on, we occasionally reviewed the other programmers' unit tests. That could be worth trying too.
 
The best situation is if you have the luxury of working with developers who have a lot of experience, then you don't need to police around but can trust the code they write.
 
Sami
GeneralRe: No easy solution.memberUltraJoe11 Nov '03 - 5:56 
I like your point about not trusting your fellow developer(s). Code development is one of those sciences that many feel is still an art. Indeed, in the 20+ years I've been in the business, I've found there's a balance of both.
 
Code reviews are only as good as the people in the review. I've seen code reviews that are nothing more than verifying the application of coding standards, e.g., this comment block is formatted properly, that line lines up with the previous, etc. Sleepy | :zzz: Unit tests, in this particular example, simply showed that each line of code was executed ... not a bad thing if the customer pays per line, but it says nothing about correctness.
GeneralIntegrating tests into automated builds is a bad thing...sussRichardC9 Nov '03 - 14:10 
Whilst I agree most of what's been written here, I find the idea of running automated tests as part of the automated build a bit worrying. It's important to keep the build enviromnent in a known and stable condition so that the builds are consistent and repeatable.
I do not want to run any unknown software - especially unreleased 'test' code - on my clean build setup. So I would contend that automated tests should be run after a build not as part of the build, although they should still form part of the acceptance checklist for the build.
 
Good article though Smile | :)
 
- Richard
GeneralRe: Integrating tests into automated builds is a bad thing...memberSami Vaaraniemi10 Nov '03 - 5:48 
By 'build', to be exact, I meant the whole build process. It typically starts with checking out the source code into a clean directory tree, then compiling the stuff, running unit tests, optionally labeling the sources etc...
 
John Lam has some pretty good (.NET-centric) material on how to implement a build system with NAnt in his Practical Eye for the .NET Guy newsletter in http://www.iunknown.com/Files/Practical_Eye_Issue1.pdf.
 
Sami
GeneralAmeneditorMarc Clifton9 Nov '03 - 13:34 
If there was one sentence in your excellent article that stood out, for me personally, it was this one:
 
The end user’s software will be a smart client with pluggable modules that can be updated independently. If you read my articles on the Application Automation Layer (AAL), you'll know why--it's my entire philosophy toward application development.
 
After writing a four part series on Unit Testing for The Code Project, I'm still not sold on the concept. One of the big stumbling blocks, in my mind, is the increasingly complex setups that the unit test must perform as you percolate up the functionality tree. Part of the answer to this lies in the use of mock objects, which add to the overhead in maintaining an application, and add to the complexity of the unit test, potentially having as many, if not more bugs, than the code you're trying to test.
 
Ultimately, when I look at the ideas behind unit testing, I think they are good but rather immature. I can see where something that automates the process of implementing a unit test, facilitates in creating sample data sets along with supporting mock objects, couples stress testing with unit tests, and simulates user actions, is a vital step to a wide acceptance of unit testing. Such a thing needs to be integrated with Visual Studio, the build process, and version control. How's that for a product idea?
 
One minor complaint. You say that:
 
Suffice it to say that writing cost effective unit tests is not trivial.
 
and I completely agree. In reading a lot of information out there on unit testing, everyone seems to say this, and no one seems to offer an answer to what "cost effective" means, and how some guidelines for the novice, given the "non-trivial" nature of good unit tests. In my questions to other CPians, I got a resounding "unit testing is a skill that must be developed". Again, there are no real guidelines. If unit testing is supposed to make software development into a real engineering discipline, then I think these questions have to be answered. In other engineering disciplines, there are ways of measuring load factor, thermal stress, force limits, etc. Why should writing cost-effective unit tests be any different? I tried to provide some guidelines in my articles, but they're rather primitive at this point. Still, it's a start.
 
Thanks for the informative article.
 
Marc

 
Latest AAL Article
My blog
Join my forum!
GeneralRe: AmenmemberDaniel Turini10 Nov '03 - 2:39 
Marc Clifton wrote:
Part of the answer to this lies in the use of mock objects, which add to the overhead in maintaining an application, and add to the complexity of the unit test, potentially having as many, if not more bugs, than the code you're trying to test.
I use unit testing as I see several benefits on its use, but this is a fundamental question on unit testing that really bothers me: why is that one expects that by adding more code to test the code reduces bugs?

 
Trying to make bits uncopyable is like trying to make water not wet.
-- Bruce Schneier

 
By the way, dog_spawn isn't a nickname - it is my name with an underscore instead of a space. -- dog_spawn

GeneralRe: AmeneditorMarc Clifton10 Nov '03 - 10:32 
Daniel Turini wrote:
I use unit testing as I see several benefits on its use, but this is a fundamental question on unit testing that really bothers me: why is that one expects that by adding more code to test the code reduces bugs?
 
I think this is a really good point. An old sig was "every line of code is a liability". I wrote a unit test once to make sure that a single function--inserting a sales transaction into the database (which involved touching multiple tables)--was working correctly. I had to write code to create the DB connection, code to read in several lookup tables to get ID's, code to create mock data, code to query the DB after it was written, and code to test the results.
 
I had more code in the unit test than the blimey function! Needless to say, I ended up debugging the unit test for a function that was working perfectly. It was faster to run the program and create a sales transaction and check the tables manually. Will I benefit from the test? Probably not, as this function will most likely never ever change.
 
Marc

 
Latest AAL Article
My blog
Join my forum!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 9 Nov 2003
Article Copyright 2003 by Sami Vaaraniemi
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid