Learning TDD
Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle. First, the developer writes an (initially failing) automated test case that defines a desired improvement or new function. Then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards. Moreover, test-driven development is related to the test-first programming concepts of extreme programming, begun in 1999, but more recently has created more general interest in its own right.
Programmers also apply the concept to improving and debugging legacy code developed with older techniques.
Test-driven development cycle
-
Add a test
In test-driven development, each new feature begins with writing a test. So, to write a test, the developer must clearly understand the feature’s specification and requirements. Moreover, the developer can accomplish this through use cases and user stories to cover the requirements and exception conditions. Also, he can write the test in whatever testing framework is appropriate to the software environment. Certainly, it could be a modified version of an existing test.
-
Run all tests and see if the new one fails
This validates that the test harness is working correctly, that the new test does not mistakenly pass without requiring any new code, and that the required feature does not already exist. Certainly, this step also tests the test itself, in the negative: it rules out the possibility that the new test always passes, and therefore is worthless. In addition, the new test should also fail for the expected reason. Moreover, this step increases the developer’s confidence that the unit test is testing the correct constraint, and passes only in intended cases.
-
Write some code
The next step is to write some code that causes the test to pass. Further, the new code written at this stage is not perfect and may. For instance, pass the test in an inelegant way. That is acceptable because it will be improved and honed in Step 5.
At this point, the only purpose of the written code is to pass the test; no further functionality should be predicted nor ‘allowed for’ at any stage.
-
Run tests
If all test cases now pass, the programmer can be confident that the new code meets the test requirements. Moreover, it does not break or degrade any existing features. However, if they do not, the new code must be adjusted until they do.
-
Refactor code
The growing code base must be cleaned up regularly during test-driven development. New code can be moved from where it was convenient for passing a test to where it more logically belongs. So, duplication must be removed. Object, class, module, variable and method names should clearly represent their current purpose and use, as extra functionality is added. Moreover, method bodies can get longer and other objects larger. Not to mention, they benefit from being split and their parts carefully named to improve readability and maintainability, which will be increasingly valuable later in the software lifecycle.
Repeat
Starting with another new test, the cycle is then repeated to push forward the functionality. Also, the size of the steps should always be small, with as few as 1 to 10 edits between each test run. However, when using external libraries it is important not to make increments that are so small as to be effectively merely testing the library itself unless there is some reason to believe that the library is buggy or is not sufficiently feature-complete to serve all the needs of the software under development.
Test structure
Effective layout of a test case ensures all required actions are completed, improves the readability of the test case, and smoothens the flow of execution. Consistent structure helps in building a self-documenting test case. A commonly applied structure for test cases has (1) setup, (2) execution, (3) validation, and (4) cleanup.
- First of all, Setup: Put the Unit Under Test (UUT) or the overall test system in the state needed to run the test.
- Secondly, Execution: Trigger/drive the UUT to perform the target behavior and capture all output, such as return values and output parameters. This step is usually very simple.
- Thirdly, Validation: Ensure the results of the test are correct. These results may include explicit outputs captured during execution or state changes in the UUT & UAT.
- Subsequently, Cleanup: Restore the UUT or the overall test system to the pre-test state. This restoration permits another test to execute immediately after this one.
Benefits
- First thing first, Test-driven development offers more than just simple validation of correctness, but can also drive the design of a program.
- Secondly, Test-driven development offers the ability to take small steps when required.
- Subsequently, It allows a programmer to focus on the task at hand as the first goal is to make the test pass.
- Moreover, TDD can lead to more modularized, flexible, and extensible code.
- Lastly, Because no more code is written than necessary to pass a failing test case, automated tests tend to cover every code path.
Limitations
- First thing first, it does not provide sufficient testing.
- Secondly, the tests may share blind spots with the code.
- Subsequently, management may feel that time spent writing tests is wasted.
- Moreover, the level of coverage and testing detail achieved during repeated TDD cycles cannot easily be re-created at a later date.
TDD and ATDD
Test-Driven Development is related to but different from Acceptance Test-Driven Development (ATDD). Not to mention, TDD is primarily a developer’s tool to help create well-written unit of code that correctly performs a set of operations. On the other hand, ATDD is a communication tool between the customer, developer, and tester to ensure that the requirements are well-defined. Also, TDD requires test automation. ATDD does not, although automation helps with regression testing.
TDD and BDD
BDD (Behavior-driven development) combines practices from TDD and from ATDD. Also, it includes the practice of writing tests first but focuses on tests which describe behavior, rather than tests which test a unit of implementation. Moreover, tools such as Mspec and Specflow provide a syntax which allows non-programmers to define the behaviors which developers can then translate into automated tests.
Make your resume stand out and become a Certified Capybara Testing Professional. Try free practice tests here!
A great career is just a certification away. So, practice and validate your skills to become Certified Capybara Testing Professional