DEV Community

Kyle Galbraith
Kyle Galbraith

Posted on • Edited on • Originally published at blog.kylegalbraith.com

How To Get Started With Test Driven Development Today

Test-driven development (TDD) is the act of writing tests before writing any code. Also known as red/green testing because you write the test, it fails, and then you write the code that makes it pass.

This process has a lot of different benefits such as simpler designs, more test coverage, and improved code quality. It provides a structure for developers to operate within that can often yield useful coding standards. If a team adopts TDD then all developers write tests for the code they write.

But if you are completely new to TDD, then getting started with it can be fuzzy. It turns out that it is quite simple to get started.

Dip Your Toes Into TDD

In the ideal world, all features have their expected behavior ahead of time. But in reality, product managers change their minds, use cases shift, and expected behaviors shift with them. This adds a twist to TDD that can be frustrating at first.

For TDD newbies, trying to write tests before a feature is even developed can be a mental blocker. You feel stuck or slowed down by TDD because the expected behaviors are not nailed down yet. Often times you have to iterate on your tests as requirements change. This is not a bad thing, but it can be a challenging place to start.

In fact, it is this twist that causes stakeholders to say "TDD is taking to long". The reality is that TDD is all about setting yourself up for faster development in the future. Every test written is a notch in the belt of better code quality and faster development.

If you are working with a legacy code base, a TDD experiment is just one bug away. Every piece of software has them, and they tend to have expected versus actual behaviors. These are great areas to start applying TDD concepts.

Follow these 7 steps to get familiar with test-driven development.

  1. The bug must be reproducible and have expected behavior.
  2. Now find where in the code the bug is at.
  3. Create a unit test that has the expected behavior.
  4. Run your new test and see that it fails.
  5. Update the code to produce the expected behavior.
  6. Run your new test again and see that it passes.
  7. Perform any refactoring on the code your test covers.

Just like that, you have applied the TDD concepts. Simple right? Almost too simple. There are some important details that I glossed over in regards to a couple of these steps.

The bug must be reproducible and have expected behavior

If there is an open question of whether is a bug than it isn't a great bug to start your TDD adventure on. Why? Because these type of bugs have unclear expected behaviors, so what is your test suppose to test?

Create a unit test that has the expected behavior

In legacy systems that have unit tests already, this might be trivial. If you are in a system that does not have any unit tests already than you are breaking new ground. With new ground comes refactoring code. Why? Because these codebases often need to be made testable. Adding dependency injection, making classes and functions single responsibility, and maybe using interfaces.

Perform any refactoring on the code your test covers

This is campsite policy, leave the code better than how you found it. If you think it is spotless, double check with someone on your team. The code is a living organism that evolves with every commit. It must be maintained, cleaned, and optimized where it can be. With good unit testing in place, you can do this maintenance and know if you broke something you shouldn't have.

What about features?

Once you are familiar with TDD concepts you should apply them to new features as well. The process is the same for the most part. Some folks write a few lines of the feature and then write the tests. Others write all the tests and then write the feature.

There is a spectrum of TDD folks that have very strong opinions on which of these correct. I am of the opinion that they are both great because there are tests either way.

What about the changing requirements? It's not a big deal. Why? Because if the requirement changes then you update your test, see it fail, and then update the code. By putting in the work to write tests before/in parallel with your feature than iterating on your feature is a breeze.

Conclusion

Test-driven development (TDD) is a very powerful tool in creating software. It enables a team to develop maintainable and high-quality code. But, it is not the only tool. Pair programming, bite-size stories, and fast iterative development are critical tools to have in place as well.

Learn AWS By Actually Using It

If you enjoyed this post and are hungry to start learning more about Amazon Web Services, I have created a new course on how to host, secure, and deliver static websites on AWS! It is a book and video course that cuts through the sea of information to accelerate your learning of AWS. Giving you a framework that enables you to learn complex things by actually using them.

Head on over to the landing page to get a copy for yourself!

Top comments (7)

Collapse
 
skatkov profile image
Stanislav(Stas) Katkov

Great article! I don't often agree fully on 'TDD advice for newbies' type of articles, but 100% with you on all these.

PS. I've been actually writing very similar article myself, but you already told 50% of my secrets ;-)

Collapse
 
markschweiger15 profile image
Mark Schweiger

Very nice!
Legacy code is a big pain and a large technical debt for many companies.
We've applied most of these steps when we started adding unit tests to our codebase.
Hope you'll make a short series on this subject :)

Collapse
 
kylegalbraith profile image
Kyle Galbraith

That is a great idea, a series of posts where we walk through some legacy code and transform it via TDD. Thank you for the tip!

Collapse
 
hilaberger92 profile image
Hila Berger

Hi Kyle, great article!
I actually started applying TDD a few months ago in my workplace, and now I read your article and it gave me new and interesting insights :)
Which languages do you work with? do you use any unit testing/mocking frameworks?

Collapse
 
kylegalbraith profile image
Kyle Galbraith

I use a variety of languages. I would say the one I have used most often would be C#. There is some great tools like NUnit and MSTest for frameworks, and NSubstitute or Moq for mocking.

Collapse
 
hilaberger92 profile image
Hila Berger

That's great!
Have you heard about Typemock by any chance?
My team and I are working with their product - Isolator, and I'm looking for some feedback from people who might use their product as well...

Collapse
 
n_develop profile image
Lars Richter

Hi @kylegalbraith ,
thanks for your post. I like the idea of starting your TDD journey by using it for bug fixes.

If you are in a system that does not have any unit tests already then you are breaking new ground.

This is so true. If you find yourself in a legacy application with no tests, I HIGHLY recommend Michael Feathers book Working Effectively with Legacy Code. It's really awesome. He shares a ton of tips on how to get your legacy app tested.