DEV Community

Cover image for Why We Test – Do things faster with Test-Driven Development
Rainer Hahnekamp
Rainer Hahnekamp

Posted on • Originally published at rainerhahnekamp.com

Why We Test – Do things faster with Test-Driven Development

As we all know, unit tests provide us with some kind of safety net. They give us a program we can use to validate that a system works the way it is supposed to – especially after we make modifications or extensions.

You are doing a lot of work up front by writing these tests. If you take the perspective that the real benefit comes during maintenance and extension work, then you will see testing as part of beautification or clearing up.

In this article I want to show that, in the context of a common web application, the typical validation process takes much longer than you think and that writing tests before the actual code will let you get the work done faster.

You may think manual checks are fast

The usual way for verifying a modification to a common web application is to validate its behavior in a browser just like an end user would do it. That means you change code, reload the browser, click on a button, and see if the expected result happens.

The duration of this process depends very much on your environment and the part of the application you are working on. If you are “lucky” to be using frameworks like Angular and Spring, their ability to support large projects comes at a price with each bootstrap and compilation. Consider this optimistic example:

  • 10-second bootstrapping
  • 5-second compilation
  • 5-second reload and test

So we are already at 20 seconds for a manual check. That assumes that your client-side and server-side build tools, like Webpack and Maven, are optimised.

Manual Checks require more time than you might think

But checks take longer than you think

However, quite often other things hugely extend the validation time. Sometimes we developers overlook typos in the first run. And in the second. (Or the third!) Each one multiplies the time you spend checking the code.

Consider the more serious case where you are working on some kind of payment functionality in an online shop. Checking whether a button triggers an appropriate action may take little time. But the typical checkout process containing fields to fill out will take much more. If you are working on long-running jobs it easily goes beyond one minute.

You could argue that using an interpreted language might speed things up. That is true, but the point here is that you easily end up having manual testing cycles, each lasting a minute, multiple times. And that’s just to validate if some lines of code had the desired effect.

TDD speeds things up

Doing TDD right – writing the test first and the code afterwards – brings you in the powerful position that you can run virtually any specific part of isolated code within seconds.

Remember that unit tests are only testing a single class. All dependencies of that class are being mocked – especially for I/O operations like databases, file systems, or networking.

Replacing manual validation with these tests improves the speed dramatically. You also end up having better quality code, but more on that in a later post. The last validation run will be the manual one. That is where you actually check if things are as they are supposed to be as an end user in the browser.

Yes, even for those special cases

You can always come up with some situations where you find it completely counter-intuitive to apply TDD.

Think about what I call “experimental work” – the trial-and-error you have to do to discover how to use a library or service you are not very familiar with. You are already working against an unknown component. Why make it more complicated by bringing a testing framework layer around your main code?

Or consider the starting phase of a web application where you are usually working on the front end part – mostly HTML and CSS with a small part of server-side code that only “moves” data from the database to the browser.

In both cases you should apply TDD from the beginning. Creating unit tests for “experimental work” lets you do the trial-and-error part faster and equips you with a toolset you can always come back to later. Your “moving data from the database to the browser” code will grow in time, resulting in an untestable codebase where you cannot run code parts isolated from each other. You will have to do the time-consuming manual tests by yourself.

TDD is worth the effort

It is your responsibility to find ways to come to testable code and integrate it in your working process. Someone is paying you as an expert. That person does not understand why you sit there waiting for an application to boot or clicking on buttons – work that a not so highly-skilled person could do.

Writing unit tests the right way is a skill you usually do not learn at universities or in normal programming education. It is hard the first time(s), and will require quite a few hours, but you will see the first results soon and never look back.

Save your time by investing in good unit tests from the beginning and start with a modularized application from the first commit.

Top comments (7)

Collapse
 
hilaberger92 profile image
Hila Berger

Great article!
"Writing unit tests the right way is a skill you usually do not learn at universities or in normal programming education. "
Do you think that universities should start teaching unit testing as a part of their programming education?

Collapse
 
rainerhahnekamp profile image
Rainer Hahnekamp

Thanks Hila. I am currently teaching programming for "intermediate beginners" and my exercises are only handed out in the form of unit tests. So the students get used to work against unit tests from their first line of code.

I know that Unit Testing is teached in universities or similar but it is considered to be more an advanced topic. So you learn it, if you have already experience in programming.

In my opinion it is really hard if you introduce Unit Tests at a later stage, because this usually means that the thinking/approach/mindset needs to be changed.

Coming back to your question: Yes, they should teach it. Absolutely.

Collapse
 
hilaberger92 profile image
Hila Berger

I think it's great you're teaching unit testing!
I agree that it's harder to learn at a later stage. I am a student myself, and my university doesn't teach unit testing.
When I started working I needed to learn about unit testing and it was very hard for me. It took me a while to understand it.
Which language do you teach? do you teach about unit testing frameworks as well?

Thread Thread
 
rainerhahnekamp profile image
Rainer Hahnekamp

Yeah, currently I am teaching Angular and Spring. So TypeScript and Java as programming language. Both have superior testing frameworks like Jasmine/Jest and JUnit & Friends (Mockito, Hamcrest,...).

Honestly, I think that all modern unit testing frameworks share the same mindset. So if you know how to write unit tests and handle mocks/spies properly in one language you can easily do the same in any other language.

Thread Thread
 
hilaberger92 profile image
Hila Berger

I agree, if you understand the principles of unit testing, you can write it in any language.
Have you heard about Typemock maybe? it's a mocking framework for C# and C++. My team and I are working with it and I'm looking for some feedback...

Thread Thread
 
rainerhahnekamp profile image
Rainer Hahnekamp

For C# I am using Moq. Is there any particular reason why you have chosen Typemock?

Thread Thread
 
hilaberger92 profile image
Hila Berger • Edited

We use Typemock Isolator. It's a user-friendly tool, that allows us to mock almost anything we need- private and static methods, constructors, ref and out parameters etc...it also integrates with a lot of unit testing frameworks such as NUnit and MSTest.
So far we are satisfied with the product, but I wanted to hear other people's opinions as well...