Have you heard of the term “test driven development”? If you’ve worked in software development before, you’ve probably heard someone mention it. In this article, I’ll explain what it is, and how to do it.
What Is Test Driven Development?
Test-driven development (or TDD) is a different approach to writing software. Normally, you write software first, then create unit tests, then run them.
With test driven development, you write the test first, then run the test, then write just enough code to fulfill the test. Then, you refactor the code (make improvements, clean it up to adhere to standards).
Because the tests run before the code exists, the test will understandably fail the first time. This is expected. Once the code is written and complete, there should be much less failure.
The tests that you run should be automated. You shouldn’t need to manually run the unit tests, as that will take a lot longer
Pros and Cons of Test Driven Development
This sounds like a strange way to develop software. Test before writing code? Why would I do that? Can’t I just write code, and then test?
Well, there are a few advantages of test driven development that I’d like to share.
- Reduce defects in production code. Because the tests are written first, you know that when you change code and a test breaks, then it was (most likely) your code that did it.
- Easier debugging. Because you test before adding code, you know what section of the code has likely caused the bug and where to look.
- Constant feedback. You have a suite of unit tests, which means that you can run them time and time again to get constant feedback on the status of the build.
- Unit tests act as documentation. The unit tests themselves can describe how the system works, and don’t go out of date, unlike separate documentation.
- Enforces critical thinking. The developers cannot create the code unless they really understand the desired result and how to test it.
- Software is often better designed. Developers can make design decisions without the risk of breaking the code significantly.
Now, while there are a lot of positives for test driven development, there are some cons or negatives for it.
- New concepts can take time to learn. If nobody in the team has done test driven development before, it can take some time to understand it.
- Partial adoption or resistance. If some team members, or the whole team, are against the idea, then it can reduce the quality of your code.
- Unit tests that are too large or too small. Tests of the wrong size can take too long to write or too long to code.
- Ongoing maintenance of unit tests required. You should be doing this anyway, but another drawback is that up-to-date unit tests are even more important in test driven development.
How Can I Perform Test Driven Development?
Are you interested in getting started with TDD?
Great. I’m a fan of it. Even though I haven’t done a lot of it, I see the benefits of it.
1 – Download and Set Up an Automated Testing Framework
The first thing you’ll need to do is download an automated testing framework for the language or tool you’re working on at the moment. This could be PHPUnit, JUnit, NUnit, or any other framework.
I won’t provide instructions on how to set that up here, but you can do a search for it and set it up.
The reason this is needed is so that you don’t need to manually run the tests every time. It saves time in development.
2 – Add Your Tests
Now you have the framework set up, you need to add your tests.
This is probably the most important part of the process. It involves analysing what needs to be done, thinking about what tests you need to create, and then creating them.
These will be the unit tests that you run consistently. They won’t be the final version, as you may tweak them and add to them later.
To start writing the tests, you’ll need to read and understand the requirements, which may be in user stories.
See the Best Practices section below for more information on adding tests.
3 – Run All Tests
Now that the tests have been written, they can be run.
When you run them for the first time, they should fail. This is expected. It’s because there is no code for the tests to run on!
If none of the tests fail for the first time, then something is wrong. You may not have written the correct tests.
It also should fail for an expected reason. If, for example, it fails because it couldn’t find a method, then that would be expected. But, if it fails because it couldn’t connect to a required service, or some other pre-check, then it may be an issue if you’re not expecting it.
4 – Write Code to Pass the Tests
At this point, you can start writing code. You should write the code that ensures the tests pass.
The code written here is not perfect, and may pass the test in a way that is not clean or neat.
This is OK though, as the refactoring for improvement will come soon.
When you write code here, it should only be to pass the test, and nothing more. You shouldn’t be writing for any future functionality or any other features.
5 – Run All Tests Again
Now, you should run all of the tests again. If the tests pass, that’s great. Your code has ensured that the original tests have passed.
If the test does not pass, then you’ll need to make some modifications to your code to get it to pass. That’s OK though, as it’s normal for this to happen as part of test driven development.
6 – Refactor Your Code
If the tests pass, then it’s now time to refactor your code.
This is where you clean it up, make sure it adheres to standards.
You would look to remove duplication, make design changes, or make performance enhancements.
Now, when you make changes as part of refactoring, you may introduce new bugs. Even though the principle of the code works, and you’ve tested it, the new changes mean that you need to run the tests again.
The good news is because the tests are automated, you can just re-run them after each change.
7 – Repeat
You can restart from step 2 if the tests pass and you have more functionality to write. The start of developing new functionality is to add tests, which is detailed in step 2.
Or, if the code does not pass return to step 4 if the tests fail. You’ll need to adjust the code to get it working and ensure the tests pass.
Best Practices for Test Driven Development
There are some best practices that developers should follow when creating test cases and perform test driven development.
- Follow a consistent structure for your tests. A common test structure is Setup, Execution, Validation, then Cleanup.
- Keep the common logic (such as setup and teardown) in separate test support services to improve code reuse.
- Ensure the test is focused on only the areas that need to be tested.
- Include tolerance in tests that require time limits.
- Ensure your test code is high quality, just like your production code. It should work for both positive and negative cases, be readable, and maintainable.
- Have regular reviews with your team to ensure best practices are being followed and to share tips.
- Avoid having tests depend on the results of other tests.
- Keep your unit tests running fast. If they are not fast, then they won’t be run often.
- Test execution results before testing timing or performance
Test driven development is a different approach to developing software, as it starts with requirements and then writing tests, before the code is written. It has many benefits, such as reduced debugging time and only working on what is needed.
Developers who are new to the concept can feel uneasy about this, especially when writing code that isn’t complete or that simulates the actual environment, but the long term benefits to the team and the system are positive.
Career Action Tip: If you’re using TDD at the moment, check your unit tests against the Best Practices list above. If you’re not using TDD, then suggest it to your team leader (and share this article with them).
Lastly, if you enjoy the information and career advice I’ve been providing, sign up to my newsletter below to stay up-to-date on my articles. You’ll also receive a fantastic bonus. Thanks!
Image courtesy of renjith krishnan / FreeDigitalPhotos.net