Test-Driven Development. How to get there (based on real-life events)
Evgeny Tkachenko
AI and Quality Transformation Leader | International Speaker | Published Author
Test-driven development (TDD) is a software development approach in which a test is written before writing the code. Once the new code passes the test, it is refactored to acceptable standards.
The following sequence of steps is generally followed:
- Add a test
- Run all tests and see if the new one fails
- Write some code
- Run tests
- Refactor code
- Repeat steps 1-5
This practice of writing failing tests, known as the ‘red-green-refactor’ cycle, focuses on writing an application code per one unit.
Each cycle should be very short.
There are tons of benefits of TDD, like:
- Getting the fastest feedback
- TDD creates a detailed living specification
- Safer Refactoring
- Fewer bugs (we find them before deployment)
- TDD enforces writing a SOLID code
- etc.
To get all of these benefits you will need to have your team-members test-infected in a good way, so everyone should write tests. They will need to be re-trained and you will need to cultivate the culture in which the whole team is responsible for the test automation and quality in general. Before you start requiring to have tests written before implementation you will to make sure your teams and the applications' code is ready for that.
Prerequisite steps:
- Change your focus to isolated unit tests and isolated component Integration tests. GUI and integration tests are slow, they don't put pressure on design, they are expensive to write and maintain and they are fragile. Do not want to put a testing pyramid here, you know what I am talking about.
- Expand the coverage. You will need to ramp it up by forming a culture of writing Unit tests for new features within the sprint and make it a part of the Definition of Done. Set quality gates on the unit test coverage for newly added functionality (for example, using SonarQube).
Test-Driven Development implementation steps:
- Make your code testable. You need to revisit what you have and refactor the existing code into testable and tested code. Refactor existing code to adhere to the SOLID principles, extract all non-testable code into wrapper-classes, get rid of static methods and variables, isolate code that is not unit-testable by nature (like external APIs).
- Organize workshops on TDD and Unit Testing. You will need to find a TDD guru (it could be an external coach) and give some workshops on that and Unit testing in general to your teams.
- Organize pair-programming sessions with those who know TDD. You will need to pair those who have never worked in such environment with those who have been there and know how to do it right.
- Set up a special sprint dedicated to getting rid of the technical debt and improve Unit-tests coverage so everyone can practice what they learned during workshops.
- Build a TDD Excellence team within the company to help other teams to follow this approach. This team will act as a consultant company within the organization, they will help everyone to stick to the TDD best practices and roll this across all of the teams.
In a couple of months after writing a decent amount of tests, you will be able to follow TDD with a couple of teams. Then you will be able to roll it out across the organization and use those teams as a role model.
Usual Complaints:
- It will slow us down. - That slowness is an illusion. Writing tests first usually means code quality will be better and there will be less need for rework and churn later, fewer defects. Eventually, it will pay off.
- Mocks add an overhead. - Since the thing you are testing doesn't exist yet, we have to rely on mock objects to simulate real objects. This does add overhead to the project, the mocks have to be created and maintained as the project changes over time. But there are a lot of tools that make it easier to do, so use them.
- We do not know what to cover by automated tests. - Behavior Driven Development (BDD) helps here, we can write requirements (acceptance criteria) with examples for the project using Domain Specific Language (DSL) which will serve as living documentation after automating those scenarios. This type of documentation is always up to date and it is a single source of truth when it comes to finding out the system behavior.
- We do not know when there will be enough tests. - BDD helps here - you will cover by automated tests only the behavior of the system (application under test) that matters most from the business point of view.
- We have a legacy application, how can we start following TDD when we have 0 unit tests? - You will go forward with baby steps, no one is going to jump from 0 unit tests to TDD with 100% coverage. Start with refactoring and making your code testable for applications that have larger value (build priority matrix) and cover them by unit tests first.
PS: When TDD properly set up, it can bring a bunch of advantages and become a cost-saver providing true value to the business. When it improperly set up or without understanding how it should be used for, it can be a waste of time and money.
The original article was published in the StickyMinds in July 2020 https://www.stickyminds.com/article/5-steps-get-test-driven-development
Senior QA Technical Lead at PTC
4 年Nice write up. I liked your 4th point in the implementation of TDD framework even after workshop by TDD guru should dedicate one sprint for practicing what has been learnt.
Passionate about building exceptional teams and equipping them to deliver extraordinary results!
4 年Great content- thanks!
Senior Software Engineer at Walmart Labs | Hiking Enthusiast
4 年Nice write Evgeny.