chapter three

3 Structural testing and code coverage

 

This chapter covers

  • Creating test cases based on the code structure
  • Combining structural testing and specification-based testing
  • Using code coverage properly
  • Why some developers (wrongly) dislike code coverage

In the previous chapter, we discussed using software requirements as the main element to guide the testing. Once specification-based testing is done, the next step is to augment the test suite with the help of the implementation code. There are several reasons to do so.

First, you may have forgotten a partition or two when analyzing the requirements, and you may notice that while looking at the source code. Second, when implementing code, you take advantage of language constructs, algorithms, and data structures that are not explicit in the documentation. Implementation-specific details should also be exercised to ensure the program’s full correctness.

3.1 Code coverage, the right way

3.2 Structural testing in a nutshell

3.3 Code coverage criteria

3.3.1 Line coverage

3.3.2 Branch coverage

3.3.3 Condition + branch coverage

3.3.4 Path coverage

3.4 Complex conditions and the MC/DC coverage criterion

3.4.1 An abstract example

3.4.2 Creating a test suite that achieves MC/DC

3.5 Handling loops and similar constructs

3.6 Criteria subsumption, and choosing a criterion

3.7 Specification-based and structural testing: A running example

3.8 Boundary testing and structural testing

3.9 Structural testing alone often is not enough

3.10 Structural testing in the real world

3.10.1 Why do some people hate code coverage?

3.10.2 What does it mean to achieve 100% coverage?

3.10.3 What coverage criterion to use

3.10.4 MC/DC when expressions are too complex and cannot be simplified

3.10.5 Other coverage criteria

3.10.6 What should not be covered?

3.11 Mutation testing