Test-Driven Development: Introduction #1
5 min read
Ever since I learned to test my code and writing code that is generally testable, it became a habit of mine to develop two codebases that each nurture each other...
- The Production Codebase
- The Test Codebase
I’ll be making a small series about TDD and how you can test the most painful stuff through an easy way
You might be asking, why should I care? After all, the code runs, and things just work...
Here is why you should care...
When you call somebody a professional software engineer, you know that he is always certain that his delivered features are 99% bug-free, and if he is asked to change or add any functionality, you are certain that this change won’t cause anything to break.
They know that every piece of the project works.
How do they know that?
By testing every piece whenever they add a new change
But that takes too much time?
They automate that process
But how do they automate that process?
By writing automated tests with high coverage
But how do they write automated tests with high coverage?
By writing TDD. 😄
Defect Injection Rate
Having a well-tested project with high test coverage means that there is a little-to-no bugs occurrence %
So in order to know if you have added any bugs to a project is by running the tests while doing any kind of change to it
This, of course, helps the QA’s life a lot, since you might be adding only Unit Tests, this will make them only care about UI Tests, which you might add as well and make QA’s life tons easier
So what happens if a bug is found? Most probably it will be something cosmetic, and less probably something essential to the business
Which in return makes for a very low Defect injection rate, or in other words, “Adding to the bugs list”
When you see bad code, normally you get an itch to refactor it, this itch is immediately followed by a sense of fear, a fear to break something if you refactor it.
Which is another reason why tests are safe proof to do any kind of change to your codebase and you will be alerted if something breaks
This is one of the main powers of writing TDD because you write the tests first, you ensure from the beginning that your code meets the requirements and that it will work whenever you change something
Ever join a team for the first time and you don’t know where to start looking? You start looking at the tests, they act as a quick way of learning about the business as they document the project in a quick way and you also learn more about the internals of the project in so little time
Not only that, it’s better than a 30+ page of manual about how a 3rd party library works.
Tests usually act as code examples, so like any programmer, you would skip those 30+ pages and look for the code examples, which might be the tests
Often when we start coding a feature, we are faced with a dilemma, how would I create that feature in a way that is well-designed?
If you follow these TDD principles, you will find out that not only you are supposed to test code that was not written, but also the way you test it, makes up for a well-designed APIs!
So what are those principles?
- You are not allowed to write any production code until you cover it with a failing test
- You are not allowed to write more of a unit test than that is sufficient to fail and compile error is considered as a failing test
- You are not allowed to write more production code than that is sufficient to make the failing test to pass
See the problem with good design and unit tests and what in fact they do have in common is...
The component needs to be isolated
so in order to test a function where this function calls other functions, you need to isolate it, so you have to think of a way to decouple it.
Which in return makes you think about good design!
Proof from bad design
If you don’t write tests first using the TDD principles, there is no force preventing you from coupling the functions into an untestable mass.
But I can always write tests later, right?
That was one of my questions to TDD, and Uncle Bob replies really gracefully here.
“No, you can’t. Not really. Oh, you can write some tests later. You can even approach high coverage later if you are careful to measure it. But the tests you write after the fact are defence. The tests you write first are offence. After-the-fact tests are written by someone who is already vested in the code and already knows how the problem was solved. There’s just no way those tests can be anywhere near as incisive as tests written first.” Excerpt From The Robert C. Martin Clean Code Collection (Collection) Martin, Robert C. This material may be protected by copyright.
Test-Driven Development is important, not just it gives you all these benefits, but it ensures a longer lifespan of a project, a happier business, and a better career