trashtime.jpg

The Purpose of Unit Testing

I was reminded yesterday that there are still many people out there who still don’t really understand the purpose of unit testing.

A funny shift happened in the last 5 or so years.

About 5 years ago, when I would suggest TDD or just doing some unit testing when creating code, I would get horrible responses back.  Many developers and managers didn’t understand why unit testing was important and thought it was just extra work.

More recently when I have heard people talking about unit testing, almost everyone agrees unit testing is a good idea, but not because they understand why, but because it is now expected in the programming world.

Progress without understanding is just moving forward in a random direction.

trashtime thumb The Purpose of Unit Testing

Getting back to the basics

Unit testing isn’t testing at all.

Unit testing, especially test driven development, is a design or implementation activity, not a testing activity.

You get two primary benefits from unit testing, with a majority of the value going to the first:

  1. Guides your design to be loosely coupled and well fleshed out.  If doing test driven development, it limits the code you write to only what is needed and helps you to evolve that code in small steps.
  2. Provides fast automated regression for refactors and small changes to the code.

I’m not saying that is all the value, but those are the two most important.

(Unit testing also gives you living documentation about how small pieces of the system work.)

Unit testing forces you to actually use the class you are creating and punishes you if the class is too big and contains more than one responsibility.

By that pain, you change your design to be more cohesive and loosely coupled.

You consider more scenarios your class could face and determine the behavior of those, which drives the design and completeness of your class.

When you are done, you end up with some automated tests that do not ensure the system works correctly, but do ensure the functionality does not change.

In reality, the majority of the value is in the act of creating the unit tests when creating the code.  This is one of the main reasons why it makes no sense to go back and write unit tests after the code has been written.

The flawed thinking

Here are some bad no-nos that indicate you don’t understand unit testing:

  • You are writing the unit tests after the code is written and not during or before.
  • You are having someone else write unit tests for your code.
  • You are writing integration or system tests and calling them unit tests just because they directly call methods in the code.
  • You are having QA write unit tests because they are tests after all.

Unit tests are a lot of work to write.  If you wanted to cover an entire system with unit tests with a decent amount of code coverage, you are talking about a huge amount of work.

If you are not getting the first primary value of unit testing, improving your design, you are wasting a crap load of time and money writing unit tests.

Honestly, what do you think taking a bunch of code you already wrote or someone else did and having everyone start writing unit tests for it will do?

Do you think it will improve the code magically just by adding unit tests without even changing the code?

Perhaps you think the value of having regression is so high that it will justify this kind of a cost?

I’m not saying not to add unit tests to legacy code.  What I am saying is that when you add unit tests to legacy code, you better be getting your value out of it, because it is hard work and costs many hours.

When you touch legacy code, refactor that code and use the unit tests to guide that refactored design.

Don’t assume unit tests are magic.

unicornmagic thumb The Purpose of Unit Testing

Unit tests are like guidelines that help you cut straight.  It is ridiculous to try and add guidelines to a word-working project after you have already cut the wood.

  • http://twitter.com/VitalyStakhov Vitaly Stakhov

    I will bookmark this for future references to share with people instead of repeating the same over and over again (hello people!) :)

    “You are writing integration or system tests and calling them unit tests just because they directly call methods in the code.”

    Amen. Just the fact that tests are using unit testing framework doesn’t make them _unit_ tests.

  • http://www.nikoslianeris.gr nikos lianeris

    very helpful article!Especially if you are new to unit testing like me!thank you for the post! :)

  • http://.catosplace.net/blogs/personal/ Peter Sellars

    Have to agree with you that there are plenty of people out there who don’t understand the purpose of unit testing.

    I have been preaching the ‘unit tests should help drive the design’ card for a while…and the way that writing the tests before the code can lead to emergent design.

    One of the things I have issues with at the moment is the need everyones seems to have for knowing their code coverage! Yes good coverage can help you to make changes to the code base but coverage is not a measure of quality.

    How can we measure the usefulness of unit tests? How do you measure the refactorable nature of code? How can we show the business benefits of unit tests driving the design? Suggestions?

  • Pingback: Back to Basics: What is an Interface? « Making the Complex Simple()

  • Shruti

    Hi,
    I am in QA, and the product I test has a lot of code written already. But, i wanted to go into the code and test it. I thought , unit testing would be a good way for it, and had been working on it, for which first I did the code coverage to know how much code the integration tests cover.

    But, after reading your post i feel that at this stage unit testing would be a waste. Could you please guide me as to what else i can do for testing the code?

    • http://simpleprogrammer.com jsonmez

      Sorry for the delayed reply.
      Here is my opinion on the matter. Trying to test quality into a product after it is developed it not a good return on investment.
      I would focus my energies on trying to put together automated functional tests and quality code practices for new code that is written.
      Also unit testing should never reveal a defect, unit tests basically repeat what the code does already, they exist to help design the code and make sure it doesn’t change in behavior.
      Hope that helps :)

  • Travis

    Thought your article was well written and honest. I am wondering though what you mean about writing integration tests and calling them unit tests? To me integration testing seems like it is just unit testing with bigger units so maybe I am doing what you are describing. I mean you still want to exercise the interface of one component as viewed by another component? In our project there are many levels of API and each one of them is an attempt to abstract the details and treat the layer as a unit.

    Again, thanks for the article.

    • http://simpleprogrammer.com jsonmez

      Thanks Travis. Integration tests in my mind are tests designed to test interconnected classes at a higher level, they may touch the database using fake data, but they don’t use mocks. Unit tests are test which test the smallest unit of code, (in most cases the class.)

  • Pingback: The Purpose of Unit Testing - Testing Excellence()

  • BigAl73

    Lol, I came here to try to understand why I don’t bother with TDD. You have convinced me more than ever that unit testing is a useless task used to help bad coder design their code better :~

    • kundrata

      I can see myself doing test driven development for my code at home, alongside using internet explorer because it’s fun and reading terms of service when installing some application.