Testing

Writing a Test Driver

After creating a class Foo, most programmers reflexively create a class called FooTester. This class contains a static main method that creates an instance of Foo and asks it to execute some of its methods.

Of course the results returned by these methods are displayed along with their expected values.

For example:

StackMachine aStackMachine = new StackMachine();
aStackMachine.push(Math.PI);
aStackMachine.push(Math.E);
aStackMachine.push(10.0);
aStackMachine.add();
aStackMachine.add();
double result = aStackMachine.peek();
double expected = Math.PI + math.E + 10.0;
System.out.println("result = " + result + ", expected = " + expected);

Implement StackMachineTester.

Using JUnit

Tests should evolve and should be run frequently. A testing framework like JUnit can be used to accomplish this.

Add JUnit:

Stack Machine>>build path>>add libraries ...

This creates an extension of JUnit's TestCase class called StackMachineTest:

public class StackMachineTest extends TestCase {
   public StackMachineTest(String name) {
      super(name);
   }

   protected void setUp() throws Exception {
      super.setUp();
   }

}

Add a test method for StackMachine.add:

This adds a test method. Test methods must have "test" as a prefix:

public class StackMachineTest extends TestCase {
   public StackMachineTest(String name) {
      super(name);
   }

   protected void setUp() throws Exception {
      super.setUp();
   }

   public void testAdd() {
      fail("test not yet implemented");
   }
}

We can now add some fixture code and test methods:

public class StackMachineTest extends TestCase {
   // fixture
   private StackMachine sm;
   private ArrayList<String> operators;
   private Double expected;

   public StackMachineTest(String name) {
      super(name);
      sm = new StackMachine();
   }

   protected void setUp() throws Exception {
      super.setUp();
      operators = new ArrayList<String>();
      operators.add("add");
      operators.add("add");
      sm.push(Math.PI);
      sm.push(Math.E);
      sm.push(10.0);
      expected = Math.PI + Math.E + 10.0;
   }

   public void testAdd() {
      try {
         setUp();
         for(String operator: operators) {
            if (operator.equals("add")) {
               sm.add();
            } // etc.
         }
         double result = sm.peek();
         assertEquals(expected, result);
      } catch(Exception e) {
        
      }
   }
  
   public void testAdd2() {
      try {
         sm.add();
      } catch(Exception e) {
         fail();
      }
   }
}

For more details see:

http://thekirschners.com/articles/how-to-write-test-cases.html

http://clarkware.com/articles/JUnitPrimer.html

http://www.junit.org/

Running JUnit Tests

With the project highlighted, select:

Run>Run As>JUnit Test

Here's a screen shot of Eclipse with the JUnit perspective:

To Do

How can a fixture be created that allows multiple tests to be run?

Hint, the fixture could be a list of scenarios. A scenario consists of a list of operands, a list of operators, and an expected result. Provide a method that tests individual scenarios. This method can be called by a method that tests lists of scenarios:

class Scenario {
   StackMachine sm;
   ArrayList<Double> operands;
   ArrayList<String> operators;
   double expected;
   void execute() {

   }
}