Our goal when writing code is to write ‘high-quality’ code, not just hack together what appears to work and moving on to the next set of functionality. When writing ‘high-quality’ software, we must test and verify that our code does what we wrote it to do and to properly handle conditions that are outside the scope of the specs (boundary conditions). Doing so will make our code more robust and reduce the likelihood of bugs being discovered later on in the development process. As you should already know, the cost of fixing bugs dramatically increases further out in the development process. If a bug is found, we can more confidently change/alter the modules to fix the bug knowing that our previously working functionality still works (by running the unit tests). If we had no tests to act as a verification of working code, we would be much more likely to introduce new bugs with our ‘bug fixes’ and not notice them.
Additionally, writing unit tests increases code quality by improving maintainability. Maintainability is just as important as getting the functionality to work because we must be able to change the software as it adapts (without breaking working functionality) and we (other) developers must be able to read the code. What is it worth to have a heap of unreadable, unmaintainable code that must be changed/fixed? Unit tests provide a way to quickly understand how the code is supposed (or not supposed) to be used. And again, it also provides that backstop against which we can verify whether or not functionality has been broken by our changes. Moreover, in an agile development team, code is ‘collectively’ owned, i.e., no one person truly owns the code; everyone should be able to read, understand, and modify the code. Unit tests greatly help a person who’s trying to read the code to make modifications confidently.
Unit testing also helps improve the design of the code. As our tests
are verifying the internals and externals of the unit of software
usually with mock or stub objects, we must design our code to be
decoupled from the rest of the system. This decoupling is usually done
by ‘programming to abstractions’ or interfaces. We cannot test the
internals of code that does not allows to swap out mock/stub
dependencies. Writing testable, decoupled code also improves design and thus code quality.
If we as professionals do not strive to improve code quality and integrity of the systems we deliver, what better are we than any offshore code sweatshop producing crap at 1/20th our bill rate? The answer’s simple. Take pride in your profession and strive for quality code or get of of this industry (you’ll be forced out by offshoring anyways… only then, you’ll be crying for government bailouts… be proactive).