Have you ever faced the challenge of having to sell unit testing to management? If you’re a software developer, then the answer is very likely “yes.” It’s also likely that your sales pitch fell flat, unfortunately. In this day and age, there are still many misconceptions about the role of unit testing that just won’t die, and management types often fall prey to them.
From “unit tests are a waste of time” to “programmers shouldn’t write tests,” there are many myths that pose obstacles to the adoption of unit testing in an organization. Today we’re focusing on just one of them, though. And it’s that you may have heard at least once in your career: “But we already have a dedicated QA department. We don’t need this unit testing stuff!”
In today’s post, we’ll show you why this line of thinking is wrong and give you the tools to counterargue and effectively adopt unit testing in your team and organization.
What Is Quality Assurance (QA)?
As it often happens in our industry, QA has become somewhat of a loaded term, making clarification indispensable.
Let’s start with the definition from Wikipedia:
Quality assurance (QA) is a way of preventing mistakes and defects in manufactured products and avoiding problems when delivering solutions or services to customers;[…]
First, notice how the definition talks about “manufactured products,” which software clearly isn’t. But Wikipedia comes to our rescue again because here we have the definition for software quality assurance:
Software Quality Assurance (SQA) consists of a means of monitoring the software engineering processes and methods used to ensure quality.
QA vs. QC
One point people often emphasize is that QA isn’t the same as QC (Quality Control), despite the fact that the two are often used interchangeably. And what are their differences? In short, QA is about prevention while QC is about verification. QA creates and constantly refines guidelines meant to ensure quality, while QC verifies that the product meets the required quality levels. It becomes clear that, in light of the above definition, testing activities belong to the QC camp. What is testing if not a form of verification?
With that being said we will, by and large, ignore those differences in this post. Yes, QA and QC are clearly different in the way they’re formally defined. But there’s no denying that in the modern software development lingo, software teams tend to group activities that should be considered QC under QA.
Let’s start out by saying that many software organizations, especially smaller ones, can’t really afford a full-fledged QA department. Sometimes this “department” consists of a single person—maybe even an intern—who provides all the manual testing demanded by the team or organization and maybe deals with some automated testing code. This is far from the ideal QA role or department, but it’s not uncommon.
Unit Testing: A Brief Overview
It would be out of the scope of this post to do an in-depth analysis of unit testing, covering this technique’s history, definition, and what-not. However, I think a brief overview is completely justified.
First of all, let’s define the term “unit test.” It seems kind of obvious that this is something that tests a unit. But what on Earth is a unit?
Unit Means ‘Unit of Work’
Well, if you ask ten different people, you’ll likely get ten different answers. The term “unit” is so controversial that some people propose to retire the term “unit testing” for good in favor of other alternatives (and I’ll get back to this point later in this post).
I tend to be a fan of Roy Osherov’s definitions. In this case, he goes beyond the common trope of defining a unit as a method, class, or set of classes. Instead, he defines a unit as a “unit of work,” or a piece of discrete, identifiable behavior of the system that visibly affects a user when he says the following:
A unit of work is a use case in the system, that is initiated by a public method somewhere, and ends up with an end result. An end result can be one of three things:
- A return value(if the public method is a function) or an exception return value
- A noticeable change to the state of the system under test. Noticeable means that the system behaves differently to an end user than it did before. For example—adding a user changes the system behavior to allow that user to login in.
- A call to a 3rd party system. A 3rd party system is a dependency that we do not have control over in our test. If it touches the file system, or calls the network, or uses threads, or anything that makes our test slow, or inconsistent, it is a dependency we don’t have control over.
Exercising a Unit of Work in Isolation
I think that’s a great definition. It certainly allows for more nuance than the black-and-white “a unit is a method” definition that most of us get when we’re first introduced to unit testing.
With that in mind, a unit test is a program that exercises one unit of the application in such a way that is completely isolated from other units, also from external dependencies such as the database or the filesystem. This isolation is required so the unit test doesn’t suffer from common problems, such as unreliability and slow speedy.
What Are Unit Tests Good for?
Up until now, all we’ve done is define things. In the first and second sections, we talked about the QA department. Then, we quickly reviewed the definition of unit testing. Now it’s finally time to join these two threads and justify our main argument for this post, which is that QA isn’t complete without unit testing.
Earlier in the post, I stated that some people want to retire the term “unit test.” Why? One of the reasons is that “unit” is often misunderstood, confusing, and poorly-defined term. An interesting suggestion I’ve seen is to call them “programmer tests” instead.
The other reason has to do with the word “test” itself. Some people argue—and I agree to some extent—that unit tests aren’t really tests. Or at least not in the way that manual exploratory testing performed by a QA person is.
Unit tests differ from most other types of software testing. Both their creators and target audience are developers. Programmers create unit tests, for programmers. More than testing in the traditional sense, unit tests are a bridge to programmer confidence.
Unit Tests Are a Path to High-Quality Software
By covering the code of the application with a suite of high-quality unit tests, developers gain confidence to refactor, which undoubtedly leads to cleaner, more readable, and more maintainable code. This suite of tests will prevent the application from turning into a mess of legacy code that programmers loathe and fear to touch. The need to write testable code will nudge the application to a saner design and architecture. This will
- Make the introduction of new errors less likely.
- Turn the software’s source code more self-documenting, which will…
- facilitate the onboarding of new team members.
In short, unit testing is a QA activity by excellence. It’s less of a verification technique and more of a tool to empower developers. To allow them to safely make choices that will lead the application to a better state.
This post was written by Carlos Schults. Carlos is a .NET software developer with experience in both desktop and web development, and he’s now trying his hand at mobile. He has a passion for writing clean and concise code, and he’s interested in practices that help you improve app health, such as code review, automated testing, and continuous build.