As I mentioned at the beginning of the class, there are many, many,
many, white box criteria. And we're not going to have time to cover them
all. So what I like to do now is just to give you
the flavor, of some other criteria by just mentioning them, and saying a
couple of things, about the way they work. And the first one I
want to mention is path coverage. And
in path coverage, the test requirements are
all the paths in the program. So what that means is that to
satisfy this criteria, we need to generate enough test cases such that all
the paths in my program are covered. As you can
imagine this is incredibly expensive because any nontrivial program has got
a virtual infinite number of paths and therefore we will
need a virtual infinite number of test cases to satisfy the
path coverage criteria. Another family of criteria I want to mention
are data-flow coverage criteria and in data-flow coverage criteria, the focus
shifts from the coverage of individual elements in the code to
the coverage of pairs of elements. And in particular the coverage
of Statements, in which the content of some memory locations
modified, and statements in which the content of the same
memory location is used. So in this way, our test
will exercise the assignments of values to memory, and the
usage of those assignments,. Finally, I want to mention mutation
coverage. And this is a fairly different and new idea,
so the key concept in mutation coverage is that we
want to evaluate the goodness of our test by modifying the code.
For example here in this small I'm, I'm showing that I might
change it. An if statement from K greater than 9, to K
greater than or equal to 9. And the reason why I want to
do that, is that if I generate enough mutants, enough variation of
my program, then I can use them to assess how good are
my tests at distinguishing the original program and the mutants. And because
I'm changing the code based on the way I expect to introduce
errors in the code, the more my test can identify mutants, the better
they are at identifying real faults. This is a very high
level [UNKNOWN], but just to give you the intuition and the idea
behind these criteria, and I'm going to provide as usual, additional pointers
to go in more depth on these topics in the notes of
the class. So now, let's go back to our test criteria
subsumption hierarchy, and see how all of these criteria fit together in
this context. Let me start with multiple condition coverage. As we saw,
MC/DC is sort of as [UNKNOWN] way of doing multiple condition coverage
in the sense that it doesn't consider all the combinations,
but only the ones that are more likely to matter.
And as such, MC/DC exercises a subset of the elements
of the multiple condition coverage
exercises. And therefore, multiple condition coverage
is more thorough than MC/DC and subsumption, and it's also
as we saw incredibly more expensive. Path coverage subsumes branch coverage,
because if I cover all of the paths in the
code, I necessarily cover all the branches. However, it doesn't subsume
multiple condition coverage, MC/CD, or
branch and condition coverage. Because this
criteria, have additional requirements involving
the conditions of the predicate that
path coverage does not have. As for data-flow coverage criteria and
mutation coverage criteria, there really no
relation with the other criteria, because
they look at different aspects, of the code. So they're not
really comparable, and therefore we're just going to put them on the
side, without any relationship with the other ones. The reason why
I want to represent them all anyways is because I want to make
an important distinction between these different criteria. And
that's the distinction between practical criteria, which are
criteria that are actually not too expansive to
be used in real scenarios. And theoretical criteria, which
are criteria that are useful in theory from
the conceptual standpoint, but they're not really applicable
in practice because they're too expansive, because they
require basically too many test cases to be satisfied.