Testing
Even though the main objective of test-driven development 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
The 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 functionality of interfaces remains unchanged, tests should pass even if internals are changed. Tester is aware of what the program should do, but does not have the knowledge of how it does it. Black-box testing is 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:
- Efficient for large segments of code
- Code access, understanding the code, and ability to code are not required
- Separation between user's and developer's perspectives
Some of the disadvantages of black-box testing are as follows:
- Limited coverage, since only a fraction of test scenarios is performed
- Inefficient testing due to tester's lack of knowledge about software internals
- Blind coverage, since tester has 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.
Tip
Automated black-box testing relies on some form of automation such as behavior-driven development (BDD).
The 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:
- Efficient in finding errors and problems
- Required knowledge of internals of the software under test is beneficial for thorough testing
- Allows finding hidden errors
- Programmers introspection
- Helps 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
- Requires high-level knowledge of internals of the software under test
- 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, has the form of unit tests.
Tip
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 quality checking is focused on defects identification, quality assurance 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 quality checking had a more important role in the past, with the emergence of TDD, acceptance test-driven development (ATDD), and later on behavior-driven development (BDD), focus has been shifting towards quality assurance.
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 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 tests' 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.