Test-driven development is a methodology in which the developer is intentionally writing the test code for a piece of code before the actual code is implemented. The general idea of this concept is to define the desired output of the code beforehand. From this expected behaviour, the test case is written. The test case will initially be failing since there is no implemented code. Based on the failing test case it should then be possible to implement the necessary functionality to make the test case pass. When the test case is successful, the functionality should be correctly implemented and tested.
After each implementation of a feature, it is recommendable to go back and refactor the implemented code to clean it up. Given that the code is written with the primary objective of fulfilling the test case, it is likely not the most “clean code”.
Should it ever become necessary to refactor the code (e.g. due to changing requirements), the process starts over again by changing the test case and afterwards change the code to make the test case pass.
TDD is a great utility, which can assist in keeping a high quality level in your code project. However, regardless of the recommendation of the methodology, I also want to highlight some of the limits of TDD. Some of these limitations are based on my own personal experience and should be evaluated as so.
Writing the testing code before the implementation theoretically sounds like a great idea. However, in reality we do not always know what type of implementation we are going to create. Perhaps I will separate the functionality into five different classes during my initial implementation. Should I then also go back and separate my test cases into five test classes? To be honest, writing test cases will in many scenarios end up taking too much time for it to be realistically feasible.
….But should we then never use TDD? No. TDD has its time and place. However, it requires a definition of what to except from the code implementation. I therefore utilize TDD when working with external interfaces in an end-to-end (E2E) test setup. Since the interface already has an explicitly define expected functionality for each API call, it will be simple and reliable to create a test case which matches this behaviour. Additionally, since it is used as and E2E test case it is not limited to one specific class.
From my experience this works great for both creating the intended functionality, maintain the quality of code, and the speed of implementation.
My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT.
I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities.
The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.
If you like the idea of that, I would encourage you to sign up for the newsletter.