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 an implementation of the old engineering joke: Good, Fast, Cheap.
public final class GoodFastCheap
{
boolean good = false;
boolean fast = false;
boolean cheap = false;
public void makeGood ()
{
good = true;
if (fast && cheap) { cheap = false; }
}
public void makeFast ()
{
fast = true;
if (good && cheap) { good = false; }
}
public void makeCheap ()
{
cheap = true;
if (fast && good) { fast = false; }
}
public void makeBad () { good = false; }
public void makeSlow () { fast = false; }
public void makeExpensive () { cheap = false; }
public boolean isSatisfactory()
{
if ((good && fast) || (good && cheap) || (fast && cheap))
return true;
return false;
}
public static void main(String[] args)
{
// Question: How well do the following tests exercise the clauses?
GoodFastCheap gfc = new GoodFastCheap(); // g f c
gfc.isSatisfactory(); // F F F
gfc.makeGood(); gfc.isSatisfactory(); // T F F
gfc.makeFast(); gfc.isSatisfactory(); // T T F
gfc.makeCheap(); gfc.isSatisfactory(); // T F T
gfc.makeSlow(); gfc.isSatisfactory(); // T F T
}
}
Focus on the predicate in isSatisfactory().
We will start with the truth table.
(Note: in reality, if tools are available, use the tools.
For practice purposes and to help you prepare for the exam: we will fill the truth table ourselves)
| Row# | g | f | c | P | Pg | Pf | Pc |
|---|---|---|---|---|---|---|---|
| 1 | T | T | T | T | |||
| 2 | T | T | T | T | T | ||
| 3 | T | T | T | T | T | ||
| 4 | T | T | T | ||||
| 5 | T | T | T | T | T | ||
| 6 | T | T | T | ||||
| 7 | T | T | T | ||||
| 8 |
Possible answer: (2, 4) -- predicate = T and predicate = F
Possible answer: (3, 6) -- (for each) clause = T and clause = F
Major clause set of possible tests
g (2,6), (2,7), (3,6), (3,7)
f (2,4), (2,7), (5,4), (5,7)
c (3,4), (3,6), (5,4), (5,6)
Assume we picked (2,6), (2,4), (3,4)
CACC-adequate test set = { 2,3,4,6 }
Major clause set of possible tests
g (2,6), (3,7)
f (2,4), (5,7)
c (3,4), (5,6)
Assume we picked (2,6), (2,4), (3,4)
RACC-adequate test set = { 2,3,4,6 }
To satisfy RACC, we first list all possible tests for each clause.
Then, based on the possible tests, select the smallest combination pairs (one for each clause).
There are various ways to achieve RACC with exactly four tests.
This exercise selects the following pairs, resulting in the minimal test set that satisfies
RACC (i.e., RACC-adequate test)
Major clause g: (2, 6)
f: (2, 4)
c: (3, 4)
Therefore, we need 4 tests (i.e., test inputs) -- rows 2, 3, 4, and 6.
Answer: [ref: https://cs.gmu.edu/~offutt/softwaretest/java/GoodFastCheapRACC.java]
public class GoodFastCheapRACC
{
// This test set achieves RACC on the predicate in the isSatisfactory() method
// inside the GoodFastCheap class. All other predicates in GoodFastCheap are ignored
// by this test set. The tests in this JUnit implement one of the possibilities,
// namely, tests 2, 3, 4, 6. Hence, the tests here are named
// reach2(), reach3(), reach4(), and reach6().
GoodFastCheap gfc;
@BeforeEach
public void setUp()
{
gfc = new GoodFastCheap(); // 8: F F F
}
@Test
public void test2() throws Exception
{
gfc.makeGood(); // 4: T F F
gfc.makeFast(); // 2: T T F
assertTrue(gfc.isSatisfactory());
}
@Test
public void test3() throws Exception
{
gfc.makeGood(); // 4: T F F
gfc.makeCheap(); // 3: T F T
assertTrue(gfc.isSatisfactory());
}
@Test
public void test4() throws Exception
{
gfc.makeGood(); // 4: T F F
assertFalse(gfc.isSatisfactory());
}
@Test
public void test6() throws Exception
{
gfc.makeFast(); // 6: F T F
assertFalse(gfc.isSatisfactory());
}
}
main() method achieve RACC?
No, it covers rows 2, 3, and 4. To achieve RACC with exactly 4 tests, we need to add either row 6 or 7
isSatisfactory()
public boolean isSatisfactory()
{
if (good && fast) return true;
if (good && cheap) return true;
if (fast && cheap) return true;
return false;
}
The RACC tests from the original method do not satisfy RACC on the refactored method.
To identify what is missing (and add the missing tests to the JUnit tests
from the previous question), the key is to analyze reachability.
RACC tests on the refactored code require tests 2, 3, 4, 5, 6, and 7.
For the third predicate, fast && cheap
RACC requires test xTT, xTF, and xFT, where x is a "don't know/care" value for the variable good.
However, these "don't know/care" values must all be false: FTT, FTF, and FFT.
Otherwise, the third predicate is not reached.
In terms of the numbering, this means that tests (rows) 5, 6, and 7 are required.
For the second predicate, good && cheap
RACC requires test TxT, TxF, and FxT, where x is a "don't know/care" value for the variable fast.
The first one must be TFT (or test 3), since TTT is impossible to achieve (that's a joke!).
The second one must be TFF (or test 4), since otherwise this predicate is not reached.
The last one we already have from the third predicate (above) and therefore,
either FTT (test 5) or FFT (test 7).
For the first predicate, good && fast
RACC requires test TTx, TFx, and FTx, where x is a "don't know/care" value for the variable cheap.
The first one must be TTF (or test 2), since TTT is impossible.
The second one can be either TFF (test 4) or TFT (test 3), both of which we already have
from the prior analysis.
The last one can be either FTF (test 6) or FTT (test 5), both of which we already have
from prior analysis.
Therefore, we need all tests except for 1 and 8.
If the RACC tests in the previous question are given (namely 2, 3, 4, and 6),
then tests 5 and 7 are missing.
CC-BY-NC-SA 4.0 license.