This exercise has two basic ideas.
One idea is to simply understand the process of "killing" mutants, along with the unfortunate companion process of identifying "equivalent" mutants.
The other idea is considering how certain mutation operators can be used to implement other coverage criteria. This second idea helps explain why mutation testing can be such a powerful coverage criterion. Consider (again) the following code:
public final class GoodFastCheap { // boolean variables good, fast, and cheap // other stuff omitted public boolean isSatisfactory() { if ((good && fast) || (good && cheap) || (fast && cheap)) { return true; } return false; } public boolean isSatisfactoryRefactored() { if (good && fast) return true; if (good && cheap) return true; if (fast && cheap) return true; return false; } }Consider a mutation operator that replaces boolean variables with the constants "T" and "F".
isSatisfactory()
?
isSatisfactoryRefactored()
?