Activity: Program mutation (Good-Fast-Cheap)

(no submission)
Purpose: Understand and apply mutation testing concept to program source code; get ready to work on homework assignment, and prepare for quiz 5 and the final exam.

You may make a copy of a worksheet and complete this activity or type your answers in any text editor.

You may work alone or with at most two other students in this course.


Consider (again) an implementation of the old engineering joke: Good, Fast, Cheap.

public final class GoodFastCheap 
{
   // boolean variables good, fast, and cheap 
   // and 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 two mutation operators, one that replaces boolean variables with the constant "true" and one that replaces boolean variables with the constant "false". (Reminder: we are considering first-order mutation testing; i.e., only one change per mutant)

  1. How many mutants do these operator generates for
    • isSatisfactory()?
    • isSatisfactoryRefactored()?
  2. Are any of these mutants "equivalent"? What is it about these mutation operators that makes this analysis easy?
  3. Some of these mutants are bound to be redundant. How many? Why?
  4. Consider a pair of corresponding mutants, one in each method. Will these mutants be killed by exactly the same tests? Is this a good thing?
  5. For each mutant, find all the tests that kill that mutant
  6. Consider the RACC-adequate tests you designed for the original isSatisfactory() and the refactored version of the isSatisfactory() methods (from Activity: Logic coverage for source code (gfc)). Compute the mutation score for each RACC-adequate test set.
    From Activity: Logic coverage for source code (gfc)
    
    You may use the RACC-tests you picked or use the following tests. 
    
    The original isSatisfactory()
    RACC-adequate test = { 2, 3, 4, 6 }           // let's call it RACC-test1  
    
    The refactored version of the isSatisfactory()
    RACC-adequate test = { 2, 3, 4, 5, 6, 7 }     // let's call it RACC-test2 

    Compute the mutation score for RACC-test1 on isSatisfactory()

    Compute the mutation score for RACC-test2 on isSatisfactoryRefactored()



You might find the following table useful. You should add more columns as needed.

  p = ((g && f) || (g && c) || (f && c))
Row g f c Original                                                                        
1 T T T                          
2 T T                            
3 T   T                          
4 T                              
5   T T                          
6   T                            
7     T                          
8                                


  p1 = (g && f) 
  p2 = (g && c) 
  p3 = (f && c)
Row g f c Original                                                                        
p1 p2 p3
1 T T T                              
2 T T                                
3 T   T                              
4 T                                  
5   T T                              
6   T                                
7     T                              
8                                    

Copyright © 2025 Upsorn Praphamontripong
Released under the Creative Commons License CC-BY-NC-SA 4.0 license.
Last updated 2025-11-09 17:28