Chapter 6.1, 6.2

What two properties must be satisfied for an input domain to be properly partitioned? 

  1. The partition must cover the entire domain (completeness)
  2. The blocks must not overlap (disjoint)

What is an Input Domain Model (IDM)?

An input domain model (IDM) represents the input space of the system under test in an abstract way.

A test engineer describes the structure of the input domain in terms of input characteristics. The test engineer creates a partition for each characteristic. The partition is a set of blocks, each of which contains a set of values. From the perspective of that particular characteristic, all values in each block are considered equivalent.

What gives more tests, each choice coverage or pair-wise coverage?

An each case coverage requires one value from each block for each characteristic. A pair-wise coverage a value from each block for each characteristic to be combined with a value from each block for each other characteristic.

Hence, a pair-wise coverage gives more tests.

Test a Calc Class

At first, this is our Calc class:

public class Calc {    
static public int add (int a, int b) {
return a + b;
}
}

It only has the add method. Hence, we made failing tests for two methods to be implemented: mult and div, for multiplication and division. 

And a failing test for the add method as well.

The input values for the addition are incorrect. Also, the mult and div message are not recognized by the class.

As we can observe, all tests failed…

testAdd failed
testDiv failed
testMult failed

Then, we changed the testAdd input values, so the test won’t fail.

Now the addition will be correct.

Next, we implemented the methods for multiplication and division in the Calc class:

Calc now has three methods

Finally, we ran the tests again and had a successfull execution.

The class recognizes all Calc methods.

Chapter 3 Team Exercise

Why do testers automate tests? What are the limitations of automation?

Because it reduces the cost of testing and human error, also it makes regression testing easier because it allows a test to be run repeatedly. Excise tasks are candidates for automation.

Although this is an essential process, it has limitations:

  • Continuous adjustment to testing code
  • Cannot be used for testing UX
  • Script reliability depends on programmer
  • Requires silo elimination

How the inheritance hierarchy can affect controllability and observability?

Having a deep inheritance tree of classes could become more complex to test, because the sub classes are dependent of its father, that means, if we modify or update something in the super class, it will affect all its respective children, which means that every test affected by the modification have to be updated for the sub classes. Therefore, inheritance does not guarantee that a method tested in the context of the super class will work correctly or in the same way that in the context of the sub class or sub classes. Thus, this affects controllability because we will need to control every super class and its sub classes, and if wee have a deep inheritance tree, it will be very complicated. On the other hand, it affects observability becase we need to observe a large number of sub classes that actually are doing the same work as the super class.

Develop JUnit tests for the BoundedQueue class.

You can find the code here.

Delete the explicit throw of NullPointerException in the Min program. Verify that the JUnit test for a list with a single null element now fails.

If we delete the line

if (result == null) throw new NullPointerException ("Min.min");

We can see that the test testForSoloNullElement() fails.

6. Consider the following example class. PrimeNumbers has three methods…

(a) A test that does not reach the fault

 @Test
void testComputePrimesA() {
PrimeNumbers primeNumbers = new PrimeNumbers();
primeNumbers.computePrimes(0);

assertEquals("[]", primeNumbers.toString());
// it never enters the while loop
}

(b) A test that reaches the fault, but does not infect

@Test
void testComputePrimesB() {
PrimeNumbers primeNumbers = new PrimeNumbers();
primeNumbers.computePrimes(7);

  assertEquals("[2, 3, 5, 7, 11, 13, 17]",
primeNumbers.toString());
}

(c) A test that infects the state, but does not propagate

 @Test
void testComputePrimesC() {
PrimeNumbers primeNumbers = new PrimeNumbers();
primeNumbers.computePrimes(8);

assertEquals("[2, 3, 5, 7, 11, 13, 17, 19]",
primeNumbers.toString());
// it is affected because it doesn't include 19
}

(d) A test that propagates, but does not reveal

This test is not possible because the faults starts at the 19 (we’re not taking in consideration 9, because it is not prime), all of subsequent primes that ends in ‘9’ won’t be in the result value.

(e) A test that reveals the fault

@Test
void testComputePrimesE() {
PrimeNumbers primeNumbers = new PrimeNumbers();
primeNumbers.computePrimes(8);

  assertEquals("[2, 3, 5, 7, 11, 13, 17, 19]",
primeNumbers.toString());
}

Exercise 7.

The computePrimes is now using the Sieve of Eratosthenes to find the primes. The first false positive result is again 9, it doesn’t print it, to reach the fault it has to compute the first 7 prime numbers. The RIPR model should be used to know if there’s a fault in our system, on the contrary, we could think that our program is running correctly, but we have so many false positives waiting to be propagated.