Unlock the Potential of Test Driven Development: Strategies to Ensure Code Quality and Confidence

Melchor Tatlonghari


Beyonce rule — “if you like it put a CI test on it” — Software Engineering at Google (O’Reilly)

Test Driven Development (TDD) is a development process in which tests are written before the code is written. It’s based on the idea of “test first, code later”. The goal of TDD is to help developers write better code and have greater confidence in its correctness. However, there are some common misconceptions about TDD that can lead to problems.

One misconception is that increasing the percentage of tests coverage should be the driving force for writing tests. While it’s important to ensure that all parts of your code are tested, focusing only on the percentage of tests coverage will not always lead to good tests. This approach is akin to addressing the effect rather than cause.

How to know if tests are good
Tests you write should give you confidence in the code
To know if your test is correct, you need to be sure that it is giving you the confidence that your code is working as expected. If a test does not pass, it should be a sign that something is wrong and needs to be fixed. A successful test should give you the confidence that your code is working correctly.

Tests breaking should give you a sigh of relief rather than a sense of dread
When a test breaks, this should be seen as an opportunity to find and fix any issues in your code. It should not be seen as an obstacle or something that needs to be done manually each time. Instead, tests should be part of the automated development workflow so they can be run with each iteration of coding to ensure everything is working correctly.

Tests should be consistently passing or failing.
1 % flakiness diminishes confidence in test suite, a workaround is retry flakey test programmatically if it cant be avoided. must be address though. — Software Engineering at Google (O’Reilly)

Tests need to remain consistent so they can accurately determine whether or not the code works as expected. If a test passes one time but fails another, then it cannot provide reliable feedback on whether or not the code works correctly. Therefore, tests must remain consistent so they can consistently provide accurate feedback on the functioning of the code.

Flakey tests are the fastest way to lose confidence in TDD. A flakey test is one which produces inconsistent results; one time a test may pass and another time it may fail for no obvious reason. This makes them unreliable and will quickly cause developers to lose confidence in TDD itself due to their inability to provide accurate results consistently across multiple runs of testing. Flakey tests should be either fixed immediately or deleted entirely.

Tests should be done automatically as part of the development workflow
Automated testing should be done as part of the development workflow for a number of reasons. It can help to reduce the amount of time spent on manual testing, making the process more efficient. Automated testing also helps to ensure consistency in quality assurance by running tests on multiple platforms at once, reducing the chance for human error.
By automating these tests, developers can have confidence that their work is being thoroughly tested without having to consciously spend time on it. This makes development faster and more reliable while also freeing up developers’ time to focus on more important tasks.
Different Approaches to Testing
DOM Testing
The more your tests resemble the way your software is used, the more confidence they can give you. — Kent C. Dodds

Sample Use Case:

One example of testing holistically is in a profile page. Here, testers must ensure that the user’s name, picture, and other details are always present. Additionally, they must verify that when submitting details on this page, the changes made will be reflected in the output.

DOM Testing — querying the rendered elements of the DOM in order to make assertions about their text content, attributes, and more

Why is it good
Testing this way is good because it doesn’t matter if another engineer changes the size, location, or color of the button or any other aesthetics. This test focuses on the core functionality of the page and makes sure those remain working correctly.

When it should break
The tests should break if an engineer changes a core functionality or removes any critical buttons from the page. In this case, an alarm should sound indicating that something was expected to be present but isn’t.

Random Testing
Random testing is an effective and efficient way to ensure that your code is being thoroughly tested. Randomizing input and asserting the output helps to cover a wide range of scenarios and results, ensuring that the code is functioning as expected. When using random testing, it is important to consider when it should be used and what potential pitfalls may arise.

When to use
Random testing should be used when you are unable to cover all possible scenarios in your assertions. This helps you cover a wider range of results and make sure that your code is functioning correctly. Additionally, it is important to have an automated run in place in order for random testing to be effective.

One potential pitfall of random testing is that it can be disguised as a flakey test if it suddenly breaks. Therefore, engineers must take the time to review any unexpected failures rather than simply rerunning the test in hopes of getting a better outcome. Additionally, engineers may not have a culture of fixing unrelated failures to their commit which can lead to further issues down the line.

Asserting outputs from the start
One good way to ensure that your code is functioning properly is to assert outputs from the start. Asserting outputs from the start involves writing tests which check for the expected output of a given function before the function has been written.

When to use
This method should be used if you are certain about what the output of a specific function will be before having written it. Additionally, this type of testing can be beneficial in putting guard rails around functions which may not have obvious outcomes.

Why is it good
So why is asserting outputs from the start a good practice? For one, it acts as documentation for future engineers who may be building on or modifying your code. Additionally, it gives you an opportunity to test different kinds of inputs and assert outputs based on how you expect your function to work. This helps ensure that any assumptions you have about how your code will behave are correct.

Test Driven Development is an effective way to ensure code accuracy and quality. TDD works by writing tests before code is written and testing the output of code before it is written. However, there are some common misconceptions about TDD which can lead to problems if not addressed. By using good approaches such as DOM Testing, Random Testing and Asserting outputs from the start, developers can have greater confidence in the correctness of their code. With these techniques in place, developers can have peace of mind that their code is accurate and reliable.