There has been a lot of talk in the software engineering world recently about Test Driven Development, or “TDD,” and whether or not it is a viable and sustainable best practice for software development or an idealistic, time consuming chore. Industry heavyweights such as David Heinemeier Hansson, Robert C. Martin aka “Uncle Bob,” and Martin Fowler have all given their opinions on TDD. In this article, we’ll look at the details of TDD, discuss automated testing in general, and explore why you should care when it relates to your software project.
What is automated testing
Software development is all about writing code that completes a set of business rules. Given certain inputs, the code delivers output, whether that is a modification to the state of something, a resulting manipulation of the input, etc. Each one of these operations can be referred to as a “feature” of the software.
Automated testing is the creation of software that tests the feature code to ensure that it is working properly and handles all of the expected scenarios of use properly. This is not only limited to testing how the software should work with proper input, but also how it should fail if invalid input or dependencies exist.
The “automated” part here is important because it is critical that the exact same test can be performed over and over exactly the same each time. Typically when talking tech about software development, there are 3 layers where different types of testing can be integrated: Unit, Integration, and Functional testing.
Unit Testing is a software testing method by which individual units of source code . . . are tested to determine if they are fit for use. Intuitively, one can view a unit as the smallest testable part of an application.
The “smallest testable part of an application” portion of the quote is what I think summarizes Unit Tests most appropriately. For example, if you had a calculator application with an “addition” function, a unit test could verify that that 5 + 5 = 10, and also that 5 + 5 does not equal 25, and so on.
It is important for Unit Tests to execute very quickly because a developer may be running a set of tests repeatedly while writing new code to ensure that nothing breaks. To that end, many developers run an “auto-test” utility that watches for changes on certain files. If a change is observed, the utility runs the appropriate tests against that file.
An Integration Test involves a combination of two or more “units” being tested. Integration Tests verify that the components of a software all work together or “integrate” appropriately.
If you are building a software on top of a development “framework,” your Integration Tests might ensure that your custom code or “domain logic” works properly with the framework functionality.
Functional Testing is a form of end to end integration test where the software is run “literally.” This testing method is concerned with “what” the software is doing with the inputs and outputs, not the “how.”
This layer of testing is where some pretty interesting tools can come into play. For example, a tool called “Selenium” can automate web browser interactions. This could be used for testing a web-based software in terms of filling out a particular form and verifying that the appropriate actions were executed or outputs created.
What is Test Driven Development – “TDD”
Test Driven Development, or TDD, is a software development process in which a failing test is written first, then feature code is created to make the test pass, then the process is repeated. Thus, the developer is always making a test first, which is why TDD is often referred to as “Test First Development.” This process ensures that there is 100% test coverage on all features, and because only enough code is written to make the test pass, there shouldn’t be any untested code.
Why you should care about automated testing
Automated testing gives your software developers confidence to make changes to the software and to know no bugs were created as a byproduct. Additionally, it allows more agility for developers who don’t hold expert knowledge of the software to confidently modify the source code without introducing error.
A developer doesn’t need to know how all areas of the software work, just that all tests pass when they start, all tests pass when they finish, and that test coverage was added for any new features created.
As a software grows and more features are added, it is a matter of time before new feature additions start to produce bugs simply because the source code is being modified. Those bugs will be discovered by the end users, and might contribute to a feeling that “your software is always broken.”
Isn’t TDD twice the work?
The short answer is no. On the surface it may seem like without TDD, time was only required to create the feature, and with TDD, you need time to create the test AND create the feature, thus doubling the development time required. What is not being considered is the amount of time required for QA testing and debugging when the feature isn’t performing properly.
Of course, there is some time requirement for creating the test – a study of three teams at Microsoft and one at IBM using TDD found that the increase in initial development time was 15% to 35%, however, the pre-release defect density (bugs that existed prior to the software being released) dropped between 40% and 90%.
Case studies were conducted with three development
teams at Microsoft and one at IBM that have adopted TDD. The results of the case studies
indicate that the pre-release defect density of the four products decreased between 40% and
90% relative to similar projects that did not use the TDD practice. Subjectively, the teams
experienced a 15–35% increase in initial development time after adopting TDD.
That 40-90% decrease in pre-release defects means that QA teams and customers weren’t finding and reporting those issues. Engineering wasn’t trying to recreate bugs and develop patches, all of which have associated costs.
The important thing to remember is that if you don’t have some kind of testing in place, you are incurring technical debt. Automation allows you to verify the test scenario in exactly the same way every time. Human QA testers may inadvertently be doing something different each time they test a functionality of a software. Hopefully this article helps you begin a discussion with your developers about their methods of testing and test automation.