Testing
Even though the main objective of TDD is the approach to code design, tests are still a very important aspect of TDD and we should have a clear understanding of two major groups of techniques, as follows:
- Black-box testing
- White-box testing
Black-box testing
Black-box testing (also known as functional testing) treats software under test as a black box without knowing its internals. Tests use software interfaces and try to ensure that they work as expected. As long as the functionality of interfaces remains unchanged, tests should pass even if internals are changed. The tester is aware of what the program should do, but does not have the knowledge of how it does it. Black-box testing is the most commonly used type of testing in traditional organizations that have testers as a separate department, especially when they are not proficient in coding and have difficulties understanding it. This technique provides an external perspective on the software under test.
Some of the advantages of black-box testing are as follows:
- It is efficient for large segments of code
- Code access, understanding the code, and ability to code are not required
- It offers separation between users and developers perspectives
Some of the disadvantages of black-box testing are as follows:
- It provides limited coverage, since only a fraction of test scenarios is performed
- It can result in inefficient testing due to tester's lack of knowledge about software internals
- It can lead to blind coverage, since testers have limited knowledge about the application
If tests are driving the development, they are often done in the form of acceptance criteria that is later used as a definition of what should be developed.
Note
Automated black-box testing relies on some form of automation, such as behavior-driven development (BDD).
White-box testing
White-box testing (also known as clear box testing, glass box testing, transparent box testing, and structural testing) looks inside the software that is being tested and uses that knowledge as part of the testing process. If, for example, an exception should be thrown under certain conditions, a test might want to reproduce those conditions. White-box testing requires internal knowledge of the system and programming skills. It provides an internal perspective on the software under test.
Some of the advantages of white-box testing are as follows:
- It is efficient in finding errors and problems
- Required knowledge of internals of the software under test is beneficial for thorough testing
- It allows finding hidden errors
- It encourages programmer's introspection
- It helps in optimizing the code
- Due to the required internal knowledge of the software, maximum coverage is obtained
Some of the disadvantages of white-box testing are as follows:
- It might not find unimplemented or missing features
- It requires high-level knowledge of internals of the software under test
- It requires code access
- Tests are often tightly coupled to the implementation details of the production code, causing unwanted test failures when the code is refactored
White-box testing is almost always automated and, in most cases, take the form of unit tests.
Note
When white-box testing is done before the implementation, it takes the form of TDD.
The difference between quality checking and quality assurance
The approach to testing can also be distinguished by looking at the objectives they are trying to accomplish. Those objectives are often split between quality checking (QC) and quality assurance (QA). While QC is focused on defects identification, QA tries to prevent them. QC is product-oriented and intends to make sure that results are as expected. On the other hand, QA is more focused on processes that assure that quality is built-in. It tries to make sure that correct things are done in the correct way.
Note
While QC had a more important role in the past, with the emergence of TDD, acceptance test-driven development (ATDD), and later on BDD, focus has been shifting towards QA.
Better tests
No matter whether one is using black-box, white-box, or both types of testing, the order in which they are written is very important.
Requirements (specifications and user stories) are written before the code that implements them. They come first so they define the code, not the other way around. The same can be said for tests. If they are written after the code is done, in a certain way, that code (and the functionalities it implements) is defining tests. Tests that are defined by an already existing application are biased. They have a tendency to confirm what code does, and not to test whether a client's expectations are met, or that the code is behaving as expected. With manual testing, that is less the case since it is often done by a siloed QC department (even though it's often called QA). They tend to work on test definition in isolation from developers. That in itself leads to bigger problems caused by inevitably poor communication and the police syndrome, where testers are not trying to help the team to write applications with quality built in, but to find faults at the end of the process. The sooner we find problems, the cheaper it is to fix them.
Note
Tests written in the TDD fashion (including its flavors such as ATDD and BDD) are an attempt to develop applications with quality built in from the very start. It's an attempt to avoid having problems in the first place.