JavaLib
 
Conversions
 
Overview
Eclipse
NetBeans
Command
BlueJ
 
Sources
Downloads
 
TSRJ Home
TSRJ Local

Conversion to Java 1.5 using the tester package

Introduction

ProfessorJ versus Java 1.5 with the tester Library

Tests as boolean expressions

Tests as boolean methods

Imperative tests

Reporting the results

We describe the differences between the syntax of test case definitions in ProfessorJ and in Java 1.5 with the tester library.

Detailed instructions for migrating from ProfessorJ to one of four possible environments: NetBeans, Eclipse, a command line controlled compilation and execution of Java programs, or BlueJ are provided in the corresponding pages.

Introduction

ProfessorJ allows you to view in the Interactions window a readable representation of the instances of data defined in the Examples class. The testing teachpack in ProfessorJ allows you to compare the actual results with the expected values and displays the complete test results. It shows the number of test that have been performed, the number of tests that failed, and for every failed test it shows both the actual and the expected values, and provides a link to the place where the failed test is located. Additionally, the testing teachpack allows the user to view the extent of the test coverage for the tests that have been run.

The tester package replicates almost all of this functionality in the context of standard Java 1.5. (The test coverage is the only missing piece.)

The test design in both environments checks whether the given actual value is the same as the expected value, comparing the objects for extensional equality. There are slight differences in the syntax of the test expressions. Additionally, in Java 1.5 the user has to learn how to invoke the Java compiler and how to run the tester.

A test that uses the tester package has the following syntax:

boolean testSomething(Tester t){
    return
        t.checkExpect(...actual..., ...expected..., [testname]) &&
        t.checkExpect(...actual..., ...expected..., [testname]) &&
        ...
        t.checkExpect(...actual..., ...expected..., [testname]);
}

The name of the test method must start with test, the method takes one argument, an instance of the Tester class, and it returns a boolean value. Each test case is an invocation of the appropriate checkExpect method by the instance of the Tester. The variants of the checkExpect methods, as well as additional methods available with the tester package are described in the Tester pages.

An instance of the Tester class invokes the test methods. This instance is a parameter for the method that invokes the tests. As long as the name of the method starts with the test and consumes one argument of the type Tester the tester package will evaluate the test cases defined within and record the results of the tests.

Because the value of every test method is a conjunction of several test cases, once a test case fails, the remaining test cases within this conjunction are not evaluated. (This is also the case for ProfessorJ testing teachpack.) We encourage the user to group together tests for every method, so that a failed result for one method does not affect the test results for other methods.

All test methods allow the user to supply an additional (third) String argument that describes this test. When provided, this String is shown in the test report.

ProfessorJ versus Java 1.5 with the tester Library

We first present an Examples class definition in ProfessorJ, show how it would look converted to Java 1.5 using the tester package, and then explain the differences.

ProfessorJ version
class Examples{
Examples() {}
 
 Flight bos_phi = new Flight("BOS", "PHI",  8, 10);
 Flight phi_hst = new Flight("PHI", "HST", 11, 13);
 Flight hst_sfo = new Flight("HST", "SFO", 14, 15);
 Flight dfw_sfo = new Flight("DFW", "SFO", 14, 15);
 
 ILoF bos_sfo = new Flight("BOS", "SFO",  9, 14);
 ILoF bos_sfo_3 = new ConsLoF(this.bos_phi, 
                   new ConsLoF(this.phi_hst, this.hst_sfo));
 ILoF bos_sfo_err = new ConsLoF(this.bos_phi, 
                     new ConsLoF(this.phi_hst, this.dfw_sfo));
                     
 // test the method departsFrom for flight itinerary classes 
 boolean testDepartsFrom(){
   return (check bos_phi.departsFrom("BOS") 
           expect true) &&
          (check bos_phi.departsFrom("PHI") expect false) &&
          (check bos_sfo.departsFrom("BOS") expect true) &&
          (check bos_sfo.departsFrom("HST") expect false);
 }
               
 // test the method departsAfter for flight itinerary classes 
 boolean testDepartsAfter = 
	      (check bos_phi.departsAfter(7) expect true) &&
          (check bos_phi.departsAfter(8) expect 
		  false) &&
          (check bos_sfo.departsAfter(7) expect true) &&
          (check bos_sfo.departsAfter(9) expect false);
 
 
 // test the method isValid for flight itinerary classes 
 boolean testIsValid(){ return 
   (check bos_phi.isValid() expect true) &&
          (check bos_sfo_err.isValid() expect false) &&
          (check bos_sfo.isValid() expect true);
 }
 
 boolean testOK = check bos_phi.depart expect 8;
 boolean testOK2(){ check bos_phi.depart expect 8;}
}

The same set of tests using the tester package will be:

import tester.*;

class Examples{
 Examples(){}
 
 Flight bos_phi = new Flight("BOS", "PHI",  8, 10);
 Flight phi_hst = new Flight("PHI", "HST", 11, 13);
 Flight hst_sfo = new Flight("HST", "SFO", 14, 15);
 Flight dfw_sfo = new Flight("DFW", "SFO", 14, 15);
 
 ILoF bos_sfo = new Flight("BOS", "SFO",  9, 14);
 ILoF bos_sfo_3 = new ConsLoF(this.bos_phi, 
                   new ConsLoF(this.phi_hst, this.hst_sfo));
 ILoF bos_sfo_err = new ConsLoF(this.bos_phi, 
                     new ConsLoF(this.phi_hst, this.dfw_sfo));
                     
 // test the method departsFrom for flight itinerary classes 
 boolean testDepartsFrom(Tester t){
   return t.checkExpect(bos_phi.departsFrom("BOS") , 
           true) &&
          t.checkExpect(bos_phi.departsFrom("PHI"),  false) &&
          t.checkExpect(bos_sfo.departsFrom("BOS"),  true) &&
          t.checkExpect(bos_sfo.departsFrom("HST"),  false);
 }
               
 // test the method departsAfter for flight itinerary classes 
 boolean testDepartsAfter(Tester t){
    return 
	      t.checkExpect(bos_phi.departsAfter(7),  true) &&
          t.checkExpect(bos_phi.departsAfter(8),  
		  false) &&
          t.checkExpect(bos_sfo.departsAfter(7),  true) &&
          t.checkExpect(bos_sfo.departsAfter(9),  false);}
 
 
 // test the method isValid for flight itinerary classes 
 boolean testIsValid(Tester t){ return 
   t.checkExpect(bos_phi.isValid(),  true) &&
          t.checkExpect(bos_sfo_err.isValid(),  false) &&
          t.checkExpect(bos_sfo.isValid(),  true);
 }
 
 boolean testOK(Tester t){
    return t.checkExpect(bos_phi.depart,  8);}
 boolean testOK2(Tester t){ t.checkExpect(bos_phi.depart,  8);} 
}

Tests as boolean expressions

In ProfessorJ the test cases can be defined in two different ways: either as a boolean field within the Examples class whose value is the result of a check expect expression, or as a method that returns a boolean value of a check expect expression. Furthermore, several check expect expressions can be combined into a conjunction expression.

A test written as a boolean field defined as a conjunction of four test results:

 // test the method departsAfter for flight itinerary classes 
 boolean testDepartsAfter = 
	   (check bos_phi.departsAfter(7) expect true) &&
          (check bos_phi.departsAfter(8) expect false) &&
          (check bos_sfo.departsAfter(7) expect true) &&
          (check bos_sfo.departsAfter(9) expect false);

translates to a method that returns a value of the conjunction of four checkExpect method invocations:

 // test the method departsAfter for flight itinerary classes 
 boolean testDepartsAfter(Tester t){
    return 
	   t.checkExpect(bos_phi.departsAfter(7),  true) &&
          t.checkExpect(bos_phi.departsAfter(8),  false) &&
          t.checkExpect(bos_sfo.departsAfter(7),  true) &&
          t.checkExpect(bos_sfo.departsAfter(9),  false);}

Tests as boolean methods

The test method definition in ProfessorJ that returns a conjunction of three check expect expressions

 // test the method isValid for flight itinerary classes 
 boolean testIsValid(){ 
    return 
          (check bos_phi.isValid() expect true) &&
          (check bos_sfo_err.isValid() expect false) &&
          (check bos_sfo.isValid() expect true);
 }

is replaced by a method that returns a value of the conjunction of three checkExpect method invocations:

 // test the method isValid for flight itinerary classes                  
 boolean testIsValid(Tester t){ 
    return 
          t.checkExpect(bos_phi.isValid(),  true) &&
          t.checkExpect(bos_sfo_err.isValid(),  false) &&
          t.checkExpect(bos_sfo.isValid(),  true);
 }

Imperative tests

All tests can be written and used in the imperative style, i.e. by invoking the test as if the method return type was void. This is a preferred style once mutation has been introduced, because it guarantees that every test will be performed. The test in the previous example would then be written as:
 // test the method isValid for flight itinerary classes                  
 void testIsValid(Tester t){ 
    return 
          t.checkExpect(bos_phi.isValid(),  true);
          t.checkExpect(bos_sfo_err.isValid(),  false);
          t.checkExpect(bos_sfo.isValid(),  true);
 }
There is no automatic conversion to this style of writing tests.

Reporting the results

Once the tests have been run the tester package prints first the value of all fields defined in the Examples class. It then reports on the tests:

---------------
Found 1 test method

Ran 3 tests.
All tests passed.

Test results: 
--------------

--- END OF TEST RESULTS ---

or, if errors have been detected the report prints both the actual and the expected value for that test and includes a link to the relevant line in the test suite:

---------------
Found 1 test methods

Ran 4 tests.
1 test failed.

Test results: 
--------------

Error in the test number 4
will fail
tester.ErrorReport: Error trace:
	at SimpleExamples.testStrings(SimpleExamples.java:12)

actual:      "hello"
expected:    "world"

--- END OF TEST RESULTS ---

last updated on Tue Oct 20 14:35:53 EDT 2009generated with PLT Scheme