One approach for Test-Driven Development

Theekshana Wijesinghe
3 min readMay 24, 2020

Force = Mass x Acceleration; is a fundamental equation in mechanics that cannot be proven to be correct. Rather, it’s correctness is derived by not being able to prove the falseness. It’s the nature of scientific theories and laws that they are falsifiable but not provable.

This is the same for the software we write, they cannot be proven to be correct (or hard ) and only can be proven to be incorrect. Tests are a way of proving the software is incorrect. Dijkstra has stated,

Testing shows the presence of bugs, not the absence.

Thus if tests show the presence of no bugs, it is not that program is correct 100% but the program is correct enough for our purpose.

While Quality Engineers try their best to find bugs and prove the software we write is incorrect, software engineers (developers) have the responsibility to avoid writing buggy codes.

TDD; Test-Driven Development is a paradigm that makes engineers have the same functionality in two places. Test and the real code. In a nutshell TDD is about initially having a failing test, then writing just enough code to make test green, then refactoring the code such that test fails and repeating the cycle until a well-tested piece of code is available.

While TDD sounds cool and guarantees a code-base with a solid test suite, it’s sometimes not practical to follow TDD, given software engineers are always in constrained environments (ex: Tight deadlines).

And it’s common that writing test is considered a burden and waste of time as it is an extra effort and done after all the functionality/code is implemented, yet it’s a metric that software engineers have to prove that the software they produce indeed does what they meant to do. Because as an industry we lack rigorous methods to prove software we produce is correct compared to other engineering disciplines. In my experience I have found the following testing strategy equipped with TDD useful and effective to produce less buggy code.

Any method/function which executes a business logic, important functionality (let’s call them as mission-critical functionality) should be tested

It’s important to get the business logic’s right, always.

Incorrect information, calculations, logic’s and such can simply make the software useless to users. Further such faults can introduce financial losses, legal issues, and many more.

Similarly important functionalities performed by an application such as network requests, database calls, and response generation methods should work correctly and predictably.

Therefore all these kinds of mission-critical functionalities should be covered with tests, guaranteeing their execution will always be correct and predictable.

Mission-critical functionalities are best tested with a TDD approach

TDD makes sure that code is repeated in two places. Inside the test suite, all the possible scenarios a mission-critical functionality will execute can be tested, this means we can identify at very early stage errors that could be present in the code such as invalid calculations, missing logical flows such as the behavior of code when values are set to null/empty and how the erroneous scenarios are handled such as exception and so on.

Therefore when used in real environments, engineers can be sure that the mission-critical functionalities are predictable and work as expected since all the possible scenarios have been identified and tested.

Writing code such that they are testable

In principle,

method/function should do one thing and one thing only.

When writing code with the idea of testing them, code tends to be smaller and modular so that it can be easy to test. In other words code tends to be much smaller, simpler, cleaner, and readable, which are the exact properties that we seek from a method.

It’s important to understand that the above-mentioned facts are subjective and there are many other ways one can follow TDD or any other testing strategy. The main goal of any testing strategy should be to identify the errors and bugs as early as possible and produce code that can be maintained, modified easily.

References

[1] Clean Architecture: A Craftsman’s Guide to Software Structure and Design (Robert C. Martin Series)

--

--