Commit bd1a1f21 authored by Thanassis Tsiodras's avatar Thanassis Tsiodras
Browse files

Improve phrasing after Andreas' feedback.

parent 6993c459
To get 100% decision coverage every decision in the program must take all To get 100% decision coverage every decision in the program must take all
possible outcomes at least once. Given that in the code we have two decisions, possible outcomes at least once. Given that in the code we have two decisions...
we need test cases that make those decisions true and false. For example, we
```c
if (a > 1 && b == 0) {
puts("Decision 1 was true");
} else {
puts("Decision 1 was false");
}
if (a == 2 || x > 1) {
puts("Decision 2 was true");
} else {
puts("Decision 2 was false");
}
```
...we need test cases that make those decisions true and false. For example, we
could have the following test cases: could have the following test cases:
a=3, b=0, x=2 → a > 1 && b == 0 (T), a == 2 || x > 1 (T) a=3, b=0, x=2 → a > 1 && b == 0 (T), a == 2 || x > 1 (T)
...@@ -21,7 +36,17 @@ Both decisions are exercised to be both true and false. ...@@ -21,7 +36,17 @@ Both decisions are exercised to be both true and false.
But notice in the gcov annotated output that all stmts are executed (there are no `####` But notice in the gcov annotated output that all stmts are executed (there are no `####`
reported in any source line in the gcov output, we have 100% statement coverage). reported in any source line in the gcov output, we have 100% statement coverage).
But there ARE branches that were never executed (because these conditions But there ARE branches that were never executed (because these conditions
were never exercised - e.g. `b` was always 0! were never exercised - e.g. `b` was always 0! Look at the last branch counter,
i.e. branch 3 of line 10:
```c
2: 10: if (a > 1 && b == 0) {
branch 0 taken 1 (fallthrough)
branch 1 taken 1
branch 2 taken 1 (fallthrough)
branch 3 taken 0
1: 11: puts("Decision 1 was true");
```
Now, if we want to get 100% condition coverage, every condition in a decision Now, if we want to get 100% condition coverage, every condition in a decision
in the program must take all possible outcomes at least once. In the code we in the program must take all possible outcomes at least once. In the code we
...@@ -46,10 +71,26 @@ we could have the following test cases: ...@@ -46,10 +71,26 @@ we could have the following test cases:
Now each condition has been both true and false, but overall, decision 1 Now each condition has been both true and false, but overall, decision 1
was NEVER true - because its two conditions were once FT, and once TF. was NEVER true - because its two conditions were once FT, and once TF.
The gcov output indicates this, in (a) the stmt coverage is not 100% (notice The gcov output indicates this, in that...
the ####) and (b) the branch coverage is also not 100%, since the FINAL
(a) the stmt coverage is not 100% - notice the `#####`:
```c
2: 10: if (a > 1 && b == 0) {
branch 0 taken 1 (fallthrough)
branch 1 taken 1
branch 2 taken 0 (fallthrough)
branch 3 taken 1
#####: 11: puts("Decision 1 was true");
call 0 never executed
-: 12: } else {
2: 13: puts("Decision 1 was false");
```
(b) ...and the branch coverage is also not 100%, since the FINAL
branch (the one that says in the object code, we've evaluated to true, branch (the one that says in the object code, we've evaluated to true,
let's execute the action of the `if`) is also not executed. let's execute the action of the `if`) is also not executed (see above,
branch 2 is taken 0 times).
Since both types of coverage are important and one does not guarantee Since both types of coverage are important and one does not guarantee
satisfying the other, in practice they are typically combined, and that is satisfying the other, in practice they are typically combined, and that is
...@@ -76,11 +117,13 @@ gcov indicates this, since there are branches that are still, never executed. ...@@ -76,11 +117,13 @@ gcov indicates this, since there are branches that are still, never executed.
For example, `a = 1` masks the condition `b == 0` in the decision `(a > 1 && b == 0)` For example, `a = 1` masks the condition `b == 0` in the decision `(a > 1 && b == 0)`
because it makes the condition `a > 1` false and therefore the executable because it makes the condition `a > 1` false and therefore the executable
doesn't need to evaluate the other condition to determine the outcome of the doesn't need to evaluate the other condition to determine the outcome of the
AND expression. Hence the need of modifying the test cases to ensure the AND expression. These are the 'short-circuit' semantics of the C language.
coverage of masking conditions, and that's called modified condition decision
coverage (MCDC): every condition in a decision has been shown to independently Hence, we need to modify the test cases to ensure the coverage of masking
affect that decision’s outcome. The test cases below satisfy MCDC coverage and conditions, and that's called modified condition decision coverage (MCDC):
therefore also satisfy decision coverage and condition coverage: every condition in a decision has been shown to independently affect that
decision’s outcome. The test cases below satisfy MCDC coverage and therefore
also satisfy decision coverage and condition coverage:
a = 2, b = 0, x = 1 → a > 1 && b == 0 (T), a == 2 || x > 1 (T) a = 2, b = 0, x = 1 → a > 1 && b == 0 (T), a == 2 || x > 1 (T)
a = 3, b = 1, x = 2 → a > 1 && b == 0 (F), a == 2 || x > 1 (T) a = 3, b = 1, x = 2 → a > 1 && b == 0 (F), a == 2 || x > 1 (T)
...@@ -88,6 +131,17 @@ therefore also satisfy decision coverage and condition coverage: ...@@ -88,6 +131,17 @@ therefore also satisfy decision coverage and condition coverage:
$ make mcdc $ make mcdc
All statements executed, all gcov-reported branches executed. At which point, all statements are executed, and all branches are reported
as executed by gcov:
$ make mcdc | grep branch
branch 0 taken 2 (fallthrough)
branch 1 taken 1
branch 2 taken 1 (fallthrough)
branch 3 taken 1
branch 0 taken 2 (fallthrough)
branch 1 taken 1
branch 2 taken 1 (fallthrough)
branch 3 taken 1
*Based on [a nice (but buggy) Quora article](https://www.quora.com/What-is-the-difference-between-decision-coverage-and-condition-coverage-when-it-comes-to-code-coverage).* *The content above is based on [a nice (but slightly buggy) Quora article](https://www.quora.com/What-is-the-difference-between-decision-coverage-and-condition-coverage-when-it-comes-to-code-coverage).*
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment