White-box testing checks the internal workings of the software rather than the user experience. It looks at the source code and follows different paths through the code, such as all of the possible branches of if...else statements.
In addition, white-box testing considers all the possible connections between the different parts of an application. So, not only will a particular unit, such as a class, be looked at, but also all of the classes within a module and all of the modules within a program.
The problem with white-box testing is that it can only identify problems in code that has been implemented. If a particular condition is marked as TODO, but no logic has been written to even call the condition, such as a simple code stub, then testing won't be able to identify that a project requirement is missing.
White-box testing can include the following:
- Application Programming Interface (API) testing: This means checking public and private APIs. An API is simply a way to interact with the program without having to know the inner workings. For example, in the preceding fuel program, using the close() method changes the position of a valve and ensures that all of the outlet flow and pressure values are set to zero. The method allows a programmer to work with the program without requiring knowledge of how the model works.
- Code coverage: This means creating tests that check the desired amount of code. It may not be possible, or necessary, to check 100% of an application, but some coding shops require a certain amount of code to be checked, whether it is a percentage of the whole code base or a certain number of classes, functions, and so on.
- Fault injection: This means intentionally feeding bad data or other faults into the software and checking the results. In security testing, fuzzing performs a similar function, where a variety of data is fed into a system to see what potential vulnerabilities exist.
- Mutation testing: This means checking the quality of software tests themselves by checking how effective they are in preventing changes to the code. The program is modified slightly (mutated) and the tests are run. The tests look for changes in the code and, hopefully, reject the changes. The percentage of mutants that are killed (caught by tests and rejected) is the rating of the test suite. Mutants often mimic programming errors, such as incorrect variables, or logic errors, such as dividing by zero.
- Static testing: This means looking at the code itself without actually running it.