Could you imagine how disastrous it could be to launch any software without testing? Just for an idea, 88% of your users will abandon your app and may never use it again if they spot a bug. Not testing your digital solutions, your cloud environments could be catastrophic. I personally don’t know anyone who would launch mobile/web apps without testing.
But just testing is not enough. We need to test it right. If we leave loopholes in our software, crackers (the bad hackers) are gonna exploit it. They will use every bug spotted to damage your finances and your brand image off-course! Well, no user likes a software with bugs, or no user likes a brand which frequently is a victim of data breaches.
So, it makes sense to invest your time and energy into setting up the right testing methodologies to ensure your apps and cloud infrastructure is secure.
Test driven development (TDD) is one of the many ways in which softwares can be developed. It’s more of an approach (extreme programming concept) to software development than a testing methodology (like unit testing, integration testing, system testing, or acceptance testing).
TDD proves handy to design, develop, and deliver apps with zero to minimal bugs. Read this insight to understand TDD in detail, and to find out if it fits your project.
What is test driven development?
TDD is based on the philosophy of writing test cases that always fails on the first execution. Intriguing? Here’s the explanation:
Traditionally, developers tend to write software code first, and then write test-cases for it. But in test driven development, the approach is different. Here, you first write the test case and then you write the code for the software you’re developing.
“Wait, what? How can we write the test case for a piece of software when it doesn’t exist?”
If that’s your reaction, it’s understandable and fair. But it is possible to write test cases before writing the software code. You do this by underscoring expected software functionalities and writing user journeys. Besides, in TDD approach, you write a lot of unit test cases for each independent class/function/module of software.
Now, before developing a function, let’s say “a function that adds a product to a cart”, you write a unit test for that function with assumed function name and execute the test. Of-course, it would fail, because it doesn’t exist right now. So, this ensures two things-
1. Confidence: when the test case finally passes, you know that the test case was written properly and the code is actually working.
2. Clarity: writing all the test case scenarios gives you a clear picture of what you need, it’s a roadmap to develop lean, sharp, high-performing softwares that would need minimal maintenance.
On a high level, TDD can be broken down into 5 steps:
1. Write test code before writing feature code.
2. Run all tests, ensure they all fail.
3. Write minimal feature code (hard code accepted as well) that passes each of the tests in the first step
4. Refactor the code for enhanced readability & maintainability. It involves removing any hard code and duplicate code, properly placing the code blocks, structuring inheritance hierarchies, adding comments, and making function names sensible.
5. Repeat the above steps.
To keep the tests small, you can adhere to the principles of KISS (keep it simple, stupid) and YAGNI (you aren’t gonna need it). To summarize, TDD enables you to focus on application testability and ensure high quality software output. We shall diver into the benefits but first let’s breeze through the best practices, the Dos and DONTs.
TDD best practices
1. Convince the top-tier management about TDD implementation.
2. Abide by the red/green/refactor cycle. Red is when test cases fail, green is when your code passes all tests, refactor is improving readability, maintainability, modularity.
3. Keep false negatives at a bay. Allow performance focused tests some tolerance while testing in non-native OS environments.
4. Prioritize development code tests as much as production code tests.
5. Avoid writing interdependent tests.
6. Avoid writing test cases for interfaces, as then it is more of integration test then unit tests. Less the test oracle, more you’re obliging to the principles of TDD.
7. Measure the TDD impact by making sharp comparative observations around developer productivity, number of bugs identified, and their resolution, etcetera.
8. Maintain proper test structures.
For example – your test case structure could include following stages:
Setup: where you write the test code to have the target test feature unit (UUT – unit under test) in the desired state.
Execution: test script that runs to check the artifacts and behavior of the software unit that is being tested.
Validation: Confirm that the outputs, behavior, return values observed as part of execution is in line with what was expected.
Cleanup: Restore the target test feature unit and its state to how it was before executing the tests.
What are the benefits & limitations of test driven development? Should you consider implementing it in your project?
1. Saves developer’s time. Studies have claimed that TDD developers tend to be more efficient. TDD, obviously, means more code-writing for developers, then just writing the feature code. So, it’s a time intensive process at-first. But in the long-run, it saves a lot of developer time that they would have invested in debugging.
2. Faster innovation, as the tests are repeatable, feedback is real quick, and thus facilitates rapid development. In TDD approach, if you’re developing the product with CI/CD pipeline and are using version control systems, then you do not need to exhaust your energy with debuggers, instead you can roll-back to the last passed version.
3. High quality software with high-readability, easy maintainability, robust & optimized code, and minimal to no bugs.
4. The features developed with TDD are lean and damn easy to test, as by design they were written to pass tests.
5. Testing coverage in TDD projects is way higher than conventional test methodologies. Testing new features with TDD framework is comparatively a lot easier as well.
6. Great fit for agile projects. TDD tests can come in handy in CI/CD processes or CI/CD pipelines like CircleCI, TravisCI, GitLab (whichever you are using for your project).
1. TDD approach is not recommended for scenarios where full functional tests might be needed to ensure proper working of a software.
2. TDD is not that effective in testing applications that involve complex user interfaces, or works excessively with databases, or relies heavily on networking configurations.
3. Writing and maintaining high number of unit tests can become a overhead if not done right.
4. Teams are prone to ignoring other tests like compliance etcetera, if TDD succeeds. This is a really bad practice and can cost projects dearly.
At Codewave, we primarily use JS and Python based technologies.
MochaJS, Karma, JEST are some of the popular testing tools for JS projects.
csUnit and Nunit are good open source unit testing technologies for .NET projects.
PyUnit, and DocTest are your go to testing technologies for Python based projects.
Junit & TestNG are good unit testing tools for Java based projects
Rspec is a popular testing framework for Ruby projects.
Software development is a vast universe, and there are multiple approaches to building the same product. Some might be better than other ones. Often, it’s not a question of best technology or best approach, rather it’s about best technology or approach for “your project, your team, your strategy”. TDD can be really productive for some of the projects, and help assist your business achieve greater agility. But only if it is done right. If things go south, TDD can be counterproductive, or ineffective. To find out what’s the right infrastructure, tech stack, and development approach for building your application, get in touch with Codewave’s digital transformation consultants.
The five steps involved in a well implemented test driven development approach include:
1. Writing a test script and adding it to the CI/CD pipeline if you’re using DevOps approach to development
2. Run the test & see if the script(s) fails
3. Write some code and iteratively test your code for bugs
4. Refactor your code to pass the test cases
Test driven development is crucial in the modern development paradigm (TDD). Mostly because it facilitates or enables faster development & innovation with an added layer of security. As the code is under test from the very beginning, the final code quality is optimum, and it is easy to maintain the repositories created with TDD development. It also hels save significant development time that goes into fixing bugs.
Pros of test driven development:
1. Modular code
2. Easy maintenance & refactoring
Cons of test driven development:
1. Initially, slows down development (but in the long run saves hell lot of time)
2. The entire development team should write proper unit tests, else the resulting code will be of degraded quality
If you are developing non GUI applications, and if the architects, consultants, and developers feel that TDD approach for the project will yield modular, and better quality post then it makes sense to go for test driven development.