On this page:
Comparing the basic types
Comparing user defined types
Comparing inexact values
Comparing Sets
Comparing Iterable collections
Comparing classes that implement the Traversal interface
Comparing Maps
Random Choice
Checking a value within a range
User-defined Equivalence
User-defined equality: ISame interface
Testing methods throwing Exceptions
Testing constructors throwing Exceptions
Testing arbitrary method invocation
Check Fail: expecting a failure
Version: 5.2.1

User’s Guide - Test Design

We include here the description of the design of all possible variants of test cases supported by the tester library. At the end of each section is a link to the test suite for that type of test cases that also serves as a comprehensive example of the use of the tester library.

Comparing the basic types

The tester allows comparison of pairs of all primitive types, or pairs of objects that are instances of the same wrapper class. An instance if a primitive type can be compared to an instance of its corresponding wrapper class as well. The tester first converts the values to the corresponding primitive type, then uses the Java == operator to validate the equality.

Sample test cases would be:

boolean testPrimitive(Tester t){

  t.checkExpect(5, new Integer(5), "should succeed");

  t.checkExpect(5, 5, "should succeed");

  t.checkExpect(new Long(5), new Integer(5), "should fail");

}

The comparison of inexact numbers (of the types double, float) or their wrapper classes is handled in the tester by checkInexact method. The programmer must provide not only the pairs objects to compare, but also the relative accuracy limit (TOLERANCE) to be used in deteremining the equality of the two objects.

Inexact numbers (double and Double or float and Float) are considered the same if their values val1 and val2 satisfy the formula:

(Math.abs(val1 - val2) / (Math.max (Math.abs(val1), Math.abs(val2))))

    < TOLERANCE;

So, we can have two tests that compare the same objects, where one test succeeds and the other fails:

boolean testDouble(Tester t){

  t.checkExpect(0.003, 0.00298, 0.001, "should succeed");

  t.checkExpect(0.003, 0.00298, 0.01, "should fail");

}

If the comparison of two objects involves a comparison of inexact numbers, the test case report contains a warning, regardless whether the test succeeds or fails, regardless whether the programmer requested the inexact comparison, or failed to do so.

Please, see the section on Inexact Values for further details, especially what happens if the two values match exactly, and how the comparison with exact zero is handled.

All tests that request exact comparison, but require inexact comparison of any fields will fail.

The classes that represent big numbers BigInteger or BigDecimal can also be compared.

The comparison of String data uses Java equals method invoked by the first String.

If both data values are null, the test succeeds, if one value is null and the other is not, the test fails.

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for the basic types tests

The complete test suite for the testing of the basic types also serves as a sample for these types of test cases. _________________________________________________________________________________

Comparing user defined types

The equality of any two instances of user defined classes is determined by comparing the pairs of values for each field defined for that class. If the field value is an instance of another class, the comparison recursively continues the comparison of the two values. Circularity in data definitions is detected.

The comparison includes all public, protected, and private fields, both those declared in this class, and those declared in the super classes. The static, volatile, and transient fields are not included in the comparison.

If the objects that are being compared contain a field of the type double or float (or their wrapper classes), the checkInexact variant of the test method must be used (see the Inexact Values section).

Here is a simple example of a class that refers to another class and the tests that check the equality of their instances:

class Book{

  String title;

  Author author;

 

  Book(String author, Author author){

    this.title = title;  this.author = author;

  }

}

 

class Author{

  String name;

 

  Author(String name){

    this.name = name;

  }

}

 

class Examples{

  Author js = new Author("John Steinbeck");

  Book tp = new Book("The Pearl", js);

 

  boolean testBooks(Tester t){

    return t.checkExpect(tp, new Book("The Pearl", js), "succeeds");

    return t.checkExpect(tp, new Book("The Pearl",

        new Author("John Steinbeck"), "succeeds");

    return t.checkExpect(tp, new Book("The Girl", js), "fails");

  }

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for user-defined types checks

The complete test suite for the testing of the user types also serves as a sample for these types of test cases. _________________________________________________________________________________

Comparing inexact values

The comparison of two objects that contain a field with the values of the types double or float (or their wrapper classes) must invoke the appropriate Inexact variant of the test method, and must provide the desired relative TOLERANCE to determine the desired accuracy of the comparison.

Inexact numbers (double and Double or float and Float) are considered the same if their values val1 and val2 satisfy the formula:

(Math.abs(val1 - val2) / (Math.max (Math.abs(val1), Math.abs(val2))))

    < TOLERANCE;

However, if either val1 or val2 is exact zero, the test checks that the absolute value of the other data is less that TOLERANCE. Otherwise, the test would always fail.

If a comparison between two objects involves inexact comparison of any two fields, the test case report, whether successful or not, includes a warning that an inexact comparison has been involved in evaluating this test case.

Note: It is important to note that a comparison of two numbers of the types double or float could succeed through direct comparison. For example new Double(5.0) == 5.0 and in that case the comparison succeeds and no warning of inexact comparison is issued. This test is performed before proceeding with the inexact comparison.

If the programmer expects two inexact values to be identical (as shown above) using the regular checkExpect variant will succeed with no warning.

If the comparison of any two objects involves inexact comparison, and the test method required exact comparison, (the programmer failed to use the Inexact variant) the test case fails and the warning is displayed as well.

Here is an example of the use of the Inexact test methods:

import tester.*;

class CartPtDouble{

  double x;

  double y;

 

  CartPtDouble(double x, double y){

    this.x = x; this.y = y;

  }

 

  double distTo0(){

    return Math.sqrt(this.x * this.x + this.y * this.y);

  }

}

 

class Examples{

  Examples(){}

 

  CartPtDouble pt = new CartPtDouble(3.0, 4.0);

  void testCartPtDouble(Tester t){

    t.checkExpect(pt.distTo0(), 5.0, "exact - will succeed");

    t.checkExpect(9.0/2.999, 3.0, "fails: should be inexact");

    t.checkInexact(9.0/2.999, 3.0, 0.000001, "fails: inaccurate");

    t.checkInexact(9.0/2.999, 3.0, 0.01, "9.0/2.999 vs. 3.0 - success");

    t.checkExpect(pt, new CartPtDouble(9.0/2.999, 4.0),

        "fails: should be inexact");

    t.checkInexact(pt, new CartPtDouble(9.0/2.999, 4.0), 0.001,

        "will succeed");

  }

}

The test report will look as follows:

Tester Prima v.1.5.1 - 17 June 2012

-----------------------------------

Tests defined in the class: Examples:

---------------------------

Examples:

---------------------------------

Tests for the class: Examples

Found 1 test methods

....

Ran 6 tests.

3 tests failed.

Issued 5 warnings of inexact comparison.

 

Failed test results:

--------------

 

Error in test number 2

9.0/2.999 vs. 3.0 fails: should be inexact

tester.ErrorReport: Error trace:

        at basics.ExamplesBasics.testCartPtDouble(ExamplesBasics.java:22)

The comparison involved inexact numbers with relative tolerance 0.0010

actual:                                 expected:

3.0010003334444812......................3.0

 

 

Error in test number 3

fails: inaccurate

tester.ErrorReport: Error trace:

        at basics.ExamplesBasics.testCartPtDouble(ExamplesBasics.java:23)

The comparison involved inexact numbers with relative tolerance 1.0E-6

actual:                                 expected:

3.0010003334444812......................3.0

 

 

Error in test number 5

fails: should be inexact

tester.ErrorReport: Error trace:

        at basics.ExamplesBasics.testCartPtDouble(ExamplesBasics.java:25)

The comparison involved inexact numbers with relative tolerance 0.01

actual:                                 expected:

 new basics.CartPtDouble:1(              new basics.CartPtDouble:1(

  this.x = 3.0..........................  this.x = 3.0010003334444812

  this.y = 4.0)                           this.y = 4.0)

 

 

--- END OF TEST RESULTS ---

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for inexact value checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Comparing Sets

The tester has a special way of comparing elements of a collection that implements the java.lang.Set interface. If the classes of the two objects match, the tester compares their sizes, then makes sure that every element in the first set appears in the second set. So, two objects of the type TreeSet or two objects of the type HashSet are compared by matching their size, then making sure every object in one set appears in the other. However, an object of the type TreeSet when compared to an object of the type HashSet will not be compared as sets. (As both are Iterable, the tester will traverse over their elements and match each pair using the regular extensional equality comparison.)

For comparing elements of a set we use the Java equals method when comparing two objects, as this is what is used to determine duplicates in a Set.

If the user implements the java.lang.Set interface for his own class, or wishes to compare any (other) two objects that are instances of classes that implement the Set interface she can invoke the comparison of the data as Sets, by using the checkSet method. There is no inexact variant of checkSet, because the set elements are again compared using the equals method.

Here is an example comparing a TreeSet and a HashSet. The first test compares two HashSets with the same data, the second test fails, because an instance of a HashSet and an instance of a TreeSet do not contain the same data in the same iterable order. The third test succeeds, as the HashSet and the TreeSet represent the same set of data:

...

Song song1a = new Song("title1", 4);

Song song1b = this.song1;

 

HashSet<Song> songSet1a =

  new HashSet<Song>(Arrays.asList(this.song1a, this.song2, this.song3));

 

HashSet<Song> songSet1b =

  new HashSet<Song>(Arrays.asList(this.song1b, this.song3, this.song2));

 

TreeSet<Song> songSet1c =

  new TreeSet<Song>(Arrays.asList(this.song1b, this.song3, this.song2));

The test cases would be:

void testSets(Tester t){

  t.checkExpect(songSet1a, songSet1b, "should succeed");

  t.checkExpect(songSet1a, songSet1c, "should fail");

  t.checkSet(songSet1a, songSet1c, "should succeed");

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for Sets checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Comparing Iterable collections

The tester has a special way of comparing elements of a collection that implements the java.lang.Iterable interface. Because all classes in the Java Collections Framework that implement the java.lang.Iterable interface contain no additional relevant data, the checkExpect and the checkInexact methods use the provided Iterator to traverse over the two collections that are being compared, matching them in the order generated by the iterator.

However, if the user implements the java.lang.Iterable interface for her own class, the checkExpect (or the checkInexact) method still examines the data within the class by comparing the values of the corresponding fields. To invoke the comparison of the data generated by the Iterator, the user needs to use the checkIterable (or the checkInexactIterable) method.

A compelling example of this scenario is when we wish to compare two recursively-built binary search trees, the first time verifying the shape of the tree, the second time wanting to see that both contain the same collection od elements, even if their shapes may differ. So, the following two trees will fail the first test, but pass the second one, assuming the iterator traverses the tree inorder:

  tree1:                    tree2:

 

     7                        4

   /   \                    /   \

  4     9                  *     9

 / \   / \                      / \

*   * *   *                    7   *

                              / \

                             *   *

The test cases would be:

void testTrees(Tester t){

  t.checkExpect(tree1, tree2, "should fail");

  t.checkIterable(tree1, tree2, "should succeed");

}

Two Arrays are similarly compared by making sure they contain the same number and types of items and every pair of corresponding items passes the equality test.

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for Iterable checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Comparing classes that implement the Traversal interface

The tester recognizes an additional interface that provides methods for traversing over the elements of a data structure. This is a functional iterator used with our students that is defined as follows:

/** An interface that defines a functional iterator

  *  for traversing datasets */

public interface Traversal<T> {

 

   /** return true if the dataset is empty */

   public boolean isEmpty();

 

   /** return the first element if available -

     *  otherwise throw an exception */

   public T getFirst();

 

   /** return the rest of this dataset if available -

     *  otherwise throw an exception */

   public Traversal<T>getRest();

}

If the user implements the Traversal interface for his own class, the checkExpect still examines the data within the class by comparing the values of the corresponding fields. To invoke the comparison of the data generated by the Traversal iterator, the user needs to use the checkTraversal (or the inexact variant, the checkInexactTraversal) method. The same examples that have been used for the checkIterable are applicable here:

  tree1:                    tree2:

 

     7                        4

   /   \                    /   \

  4     9                  *     9

 / \   / \                      / \

*   * *   *                    7   *

                              / \

                             *   *

The test cases would be:

void testTrees(Tester t){

  t.checkExpect(tree1, tree2, "should fail");

  t.checkTraversal(tree1, tree2, "should succeed");

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for Traversals checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Comparing Maps

The tester checks whether the objects to be compared are instances of a class that implements the Java Map interface. This includes the HashMap and TreeMap classes in the Java Collections Framework.

For these objects the tester uses the Map methods to determine whether the two maps are of the same size, validates that they define the same key sets, and then validates that for each key-value pair in the first map there exists a matching key-value pair in the second map.

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for Map checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Random Choice

At times a method produces one of several random values. As long as the number of possible choices is fixed (and reasonably small) the tester can be used to determine whether the produced value matches one the possible given values. The comparison of the actual value with each of the possible expected values follows the same rules as the direct comparison of data.

The following example illustrates such tests. The test method is named checkOneOf:

public void testReply(Tester t){

 

  String s = answers.randomAnswer();

  t.checkExpect(s.equals("Why do you want to know?") ||

                 s.equals("Who cares?") ||

                 s.equals("It does not matter."));

 

 

  t.checkOneOf("The test should succeed :)",

                      s,

                      "Why do you want to know?",

                      "Who cares?",

                      "It does not matter.");

 

  t.checkOneOf("The test should fail :(",

                      "HI",

                      "Why do you want to know?",

                      "Who cares?",

                      "It does not matter.");

}

In contrast, we also support the test that assures that the actual value is not one of the given selection of possible values.

The following example illustrates such test. The test method is named checkNoneOf:

t.checkNoneOf("The test should succeed :)",

                      "HI",

                      "Why do you want to know?",

                      "Who cares?",

                      "It does not matter.");

 

t.checkNoneOf("The test should fail :(",

                      "Who cares?",

                      "Why do you want to know?",

                      "Who cares?",

                      "It does not matter.");

Inexact variants for both method are also available, though we do not expect them to be used extensively.

Here is an example:

double myGrade = 3.001;

t.checkInexactOneOf("The test should succeed :)",

                      0.01,     // the tolerance

                      myGrade,  // actual value

                      3.333,

                      3.0,

                      2.666);

 

t.checkInexactOneOf("The test should fail :(",

                      0.01,     // the tolerance

                      myGrade,  // actual value

                      3.333,

                      3.5,

                      2.666);

 

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for random choice checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Checking a value within a range

At times we just want to make sure the expected value falls within the given range. The tester supports three variants of such range checks. For every variant the programmer supplies the actual value and the lower and upper bounds for the desired range. Additional arguments may specify whether the bounds are inclusive or exclusive (see below).

The first variant, the method checkNumRange, defines the comparison of arbitrary numerical values, allowing (for example) for mixing double range with int actual values and vice versa:

t.checkNumRange(5, 0, 4.9, "fails");

t.checkNumRange(5, 0, 5.0, false, true,

      "succeeds: inclusive upper bound");

t.checkNumRange(0.0, 0, 5.0, false, true,

      "fails: exclusive lower bound");

The second variant the method checkRange accepts the actual value (and the desired lower and upper bounds) of the type that implements the Comparable interface. All wrapper classes for the primitive types implement this interface, but require that the argument matches the invoking wrapper class. That means, for example, that we can use this variant to compare the actual int value within int bounds, but need to use the checkNumRange variant if the types are mixed.

The third variant, the method checkRange, accepts three values of arbitrary type <T> together with an Comparator<T> object that allows us to compare the actual value with the given lower and upper bounds.

In all three variants, by default, the test uses the inclusive lower bound and the exclusive upper bound . The user may supply two additional boolean values that determine whether the lolowerwer bound and the upper bound should be inclusive.

The following example illustrates the use of the checkRange tests:

public void testReply(Tester t){

 

  String aaa = "aaa";

  String abc1 = "abc";

  String abc2 = "abc";

  String bcd = "bcd";

  String cde = "cde";

  String cde2 = "cde";

  String def = "def";

  t.checkRange(aaa, abc1, cde,

        "fails: aaa is below low: [abc cde)");

  t.checkRange(abc2, abc1, cde,

         "abc is equal low: [abc cde)");

  t.checkRange(abc2, abc1, cde, false, true,

         "abc is equal low: [abc cde)");

  t.checkRange(bcd, abc1, cde,

         "bcd is within range: [abc cde)");

  t.checkRange(cde, abc1, cde,

         "fails: cde equals high: [abc cde)");

  t.checkRange(cde, abc1, cde, true, true,

         "succeedss: cde equals high: [abc cde)");

  t.checkRange(def, abc1, cde,

         "fails def is above high: [abc cde)");

 

  Book p = new Book("Pearl", "JS");

  Book c = new Book("Cosmos", "CS");

  Book h = new Book("Hamlet", "WS");

 

   t.checkRange(h, c, p,

                       new Comparator<Book>(){

                       public int compare(Book b1, Book b2){

                           return b1.title.compareTo(b2.title);

                       }}, "Hamlet between Cosmos and Pearl");

 

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for range checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

User-defined Equivalence

The tester checks whether the two given objects are equivalent according to the given user-defined function object that implements the Equivalence interface.

The Equivalence interface is defined as:

public interface Equivalence<T>{

  // are the two objects equivalent?

  public boolean equivalent(T t1, T t2);

}

It is assumed, but not required, that the implementation of the Equivalence interface represents a true equivalence relation, i.e. is reflexive, symmetric and transitive.

The following example illustrates the use of the checkEquivalent tests:

For the class that represents a Book with an Author we define two books to be equivalent if their author has the same name:

public class EquivBooks implements Equivalence<Book>{

 

  // two books are equivalent if the author's names match

  public boolean equivalent(Book b1, Book b2){

    return b1.author.name.equals(b2.author.name);

 }

}

We now run the following tests:

// sample books

public Author author1=new Author("author1",40);

public Author author2=new Author("author2",55);

public Author author3=new Author("author1",66);

public Author author4=new Author("author4",26);

 

// sample authors

public Book book1=new Book("title1",author1,4000);

public Book book2=new Book("title2",author2,4000);

public Book book3=new Book("title3",author3,3001);

public Book book4=new Book("title1",author4,4000);

 

// instance of the Equivalence

Equivalence equbooks = new EquivBooks();

 

void testEquivalence(Tester t){

  t.checkEquivalent(this.book1, this.book2, equbooks,

    "fails: different books, authors");

  t.checkEquivalent(this.book1, this.book3, equbooks,

    "should succeed - same author names");

  t.checkEquivalent(this.book1, this.book4, equbooks,

    "fails: different authors.");

  t.checkEquivalent(this.book1, this.book3, equbooks); // no testname

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for checks that use the Equivalence interface

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

User-defined equality: ISame interface

The programmer may decide that for one or more classes in his program the equality comparison should always be handled in a special way (e.g. only some of the fields have to match, or that Strings should be compared in a case-insensitive manner), but for some reason, the programmer does notwant to override the equals method for the class. In this case these classes should implement the tester.ISame interface (defined in the tester package) by defining the method same that compares this object with the given one. Any two instances of a class that implements the ISame interface will be compared by applying the same method defined in that class. The remainder of the test evaluation follows the regular rules.

The ISame interface is defined as:

// provide a customized comparison of objects in this class

public interface ISame<T>{

 

  // it this object the same as the given one?

  public boolean same(T that);

}

The following example illustrates the use of the tests that apply the user-defined same method:

For the class that represents an Author we define two authors to be same if their last names are the same:

public class Author implements ISame<Author>{

  String lastName;

  String firstName;

 

  Author(String lastName, String firstName){

    this.lastName = lastName;

    this.firstName = firstName;

  }

 

  // two authors are same if their last names match

  public boolean same(Author that){

    return this.lastName.equals(that.lastName);

 }

}

We now run the following tests:

// sample books

public Author sk=new Author("King", "Steven");

public Author dk=new Author("King", "Dan");

public Author db=new Author("Brown", "Dan");

 

// sample authors

public Book book1=new Book("title1",sk,4000);

public Book book2=new Book("title2",db,4000);

public Book book3=new Book("title1",db,4000);

public Book book4=new Book("title1",dk,4000);

 

void testSame(Tester t){

  t.checkExpect(this.book1, this.book2,

    "fails: different books, authors");

  t.checkExpect(this.book1, this.book4,

    "should succeed - same author last names");

  t.checkExpect(this.book3, this.book4

    "fails: different author last names.");

  t.checkExpect(this.book2, this.book3

    "fails: different titles.");

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for checks that implement ISame interface

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Testing methods throwing Exceptions

The tester also allows the user to test whether a method invocation by the given instance and with the given arguments throws the expected Exception with the message the programmer expects. The tester will report every type of failure - when the method fails to throw exception, when the method throws an exception of a different type, when the method throws an exception of the correct type, but with a wrong message.

An example of such test is shown below:

// A test for exceptions

// -- this code is expected to throw an exception of the given type

//  but with a different message - and the test should fail

public void testExceptions(Tester t){

  /** A test that throws an exception */

  t.checkException(

    // the test name - information about this test

    "new MTListTr().getRest() \n" +

    "The test should fail: we supplied a wrong message",

 

    // the expected exception and message

    new UnsupportedOperationException(

      "No first element in an empty data set"),

 

    // the instance that invokes the method

    new MTListTr<Object>(),

 

    // the method name

    "getRest"

 

    // the comma-separated argument list ( or no arguments)

    );

}

This tester reports the failure of this test as follows:

Error in the test number 103

new MTListTr().getFirst()

The test should fail: we supplied a wrong message

 correct exception:

 class: java.lang.UnsupportedOperationException

 incorrect message: No rest in an empty data set

 

tester.ErrorReport: Error trace:

        at samples.Examples.testExceptions(Examples.java:626)

 

actual:      "message produced: No rest in an empty data set"

expected:    "message expected: No first element in an empty data set"

Note: If the test results in throwing an incorrect exception, the diagnostic message is more detailed. It includes the expected exception, the name of the method, and the object that invoked the method. This should help in identifying errors in setting up the test case, as well as in the error diagnosis. The error shown below was caused by misspelling the name of the method in the test case:

 incorrect exception was thrown:

 exception thrown:   java.lang.NullPointerException

 exception expected: java.lang.RuntimeException

    with the message: Variable does not have a value

    after invoking the method evalx

    by an object in the class: BinOp

    object value was:

((5 > 8) && t)

 new BinOp:1(

  this.op =  &&

   new AndOp:2()

  this.rand1 = (5 > 8)

   new BinOp:3(

    this.op =  >

     new GreaterThan:4()

    this.rand1 = 5

     new Value:5(

      this.data = 5)

    this.rand2 = 8

     new Value:6(

      this.data = 8))

  this.rand2 = t

   new BoolVar:7(

    this.identifier =  "t"))

 

tester.ErrorReport: Error trace:

        at Examples.testExpEval(Expression.java:439)

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for exception checks

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Testing constructors throwing Exceptions

The tester also allows the user to test whether a constructor invocation for the given class and with the given arguments throws the expected Exception with the message the programmer expects. The tester will report every type of failure - when the constructor fails to throw exception, when the constructor throws and exception of a different type, when the constructor throws an exception of the correct type, but with a wrong message.

An example of such test is shown below:

// A test for exceptions

// -- this code is expected to throw an exception of the given type

//  but with a different message - and the test should fail

public void testConstructorExceptions(Tester t){

  /** A test that throws an exception */

  t.checkConstructorException(

    // the test name - information about this test

    "new Date(4000, 10, 29) \n" +

    "The test should fail: we supplied a wrong message",

 

    // the expected exception and message

    new IllegalArgumentException(

      "Invalid yeer in Date."),

 

    // the class name

    "MyDate",

 

    // the comma-separated argument list ( or no arguments)

    4000, 10, 29

    );

}

This tester reports the failure of this test as follows:

Error in test number 2

 

 correct exception:

 class: java.lang.IllegalArgumentException

 incorrect message:

 

 message produced: Invalid year in Date.

 message expected: Invalid yeer in Date.

 after invoking the constructor for the class MyDate

 

tester.ErrorReport: Error trace:

        at ExamplesDates.testWithin(Date.java:65)

        at ExamplesDates.main(Date.java:82)

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for checks of exceptions thrown by the constructors

Tests for constructor exceptions are included with general exceptions tests.

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

Testing arbitrary method invocation

The tester defines the method checkMethod that allows the programmer to test the expected value produced by a method invocation by providing the expected value, the instance that invokes the method, the method name, and the arguments that the method consumes. If the expected object contains inexact value the programmer must use the checkInexactMethod variant to define the test.

The examples below illustrate both versions:

public class Song{

 

  protected String title;

  private int time; // the playing time

 

  public Song(String title, int time){

    this.title=title;

    this.time=time;

  }

 

  // Determine if the total playing time

  // for this and the two given songs is 10

  public boolean tenMinutesTotal(Song two, Song three){

    return this.time + two.time + three.time == 10;

  }

 

  // Is the playing time for this song shorter than for that song?

  private Song shorter(Song that){

    if (this.time < that.time)

      return this;

    else

      return that;

  }

}

 

// Tests:

class Examples{

Song song1 = new Song("title1", 4);

Song song2 = new Song("title2", 2);

Song song1a = new Song("title1", 4);

 

public void testMethods(Tester t){

  // test this.song1.shorter(this.song2) -- expect song1

  t.checkExpect("Check if you get the shorter song -- should fail",

                this.song1,       // expected value

                this.song1,       // object that invokes the method

                "shorter",        // method name

                this.song2);      // method arguments

 

  // test song1.tenMinutesTotal(song1a, song2) -- expect true

  t.checkExpect("Check if the total playing time is 10 -- should succeed",

                true                       // expected value

                this.song1,                // object that invokes the method

                "tenMinutesTotal",         // method name

                this.song1a, this.song2);  // method arguments

}}

Here is an example that uses the checkInexactMethod variant of the method:

class CartPtDouble{

  double x;

  double y;

 

  CartPtDouble(double x, double y){

    this.x = x; this.y = y;

  }

 

  // compute the distance from this point to the origin

  double distTo0(){

    return Math.sqrt(this.x * this.x + this.y * this.y);

  }

 

  // compute the distance to the given point

  double distTo(CartPtDouble that){

    return Math.sqrt((this.x - that.x) * (this.x - that.x) +

                     (this.y - that.y) * (this.y - that.y));

  }

}

 

class Examples{

  Examples(){}

 

  void testMethodInvocation(Tester t){

        t.checkMethod("exact - will succeed", 5.0, this.pt, "distTo0");

        t.checkInexactMethod("inexact check - success",

                             4.998,

                             0.001,

                             this.pt,

                             "distTo",

                             new CartPtDouble(7.0, 7.0));

  }

}

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for checks of arbitrary method invocations

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________

CheckFail: expecting a failure

At times the user may want to set up a test that verify that the actual value differs from the expected value. The tester supports this version of tests with the checkFail method. It works for the primitive types, the wrapper classes, the user defined types, as well as Traversals and Maps.

Please, consults the Tester APIs link or the formal documentation for details for each specific case.

Here is a simple example of its use:

public class Song{

 

  protected String title;

  private int time; // the playing time

 

  public Song(String title, int time){

    this.title=title;

    this.time=time;

  }

 

  // Produce a new song with the same title, but decreased time

  public Song changedTime(int dec){

    return new Song(this.title, this.time - dec;

  }

}

 

// Tests:

class Examples{

Song song1 = new Song("title1", 4);

Song song2 = new Song("title2", 2);

 

public void testMethods(Tester t){

  // make sure the time has been changed...

  t.checkFail(song1.changedTime(2), song1);

}}

A similar variant can be used to verify that an inexact comparison fails. The method checkInexactFail works for the prinitive types, the wrapper classes, the user defined types, as well as Traversals and Maps.

Caution: The test checkInexactFail fails when the two values involved in the comparison are of the primitive types or are instances of wrapper classes that represent exact values (i.e. whole numbers, characters, boolean values, and bytes). Therefore, the corresponding checkInexactFail test will succeed.

Here are examples of its use:

// test should succeed:

t.checkInexact(123000.0, 128000.0, 0.1);

 

// test should fail:

t.checkInexactFail(123000.0, 128000.0, 0.1);

 

// test should fail:

t.checkInexact(143000.0, 128000.0, 0.1);

 

// test should succeed:

t.checkInexactFail(143000.0, 128000.0, 0.1);

 

// test should fail (comparing exact values):

t.checkInexact(123000, 128000, 0.1);

 

// test should succeed (comparing exact values):

t.checkInexactFail(123000, 128000, 0.1);

The last two cases will produce the messages:

Attempt to make inexact comparison of exact primitive or wrapper data.

and

Test failed because we cannot make inexact comparison of exact primitive or wrapper data.

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for checkFail

Tests for checkFail variant are included with user types tests.

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

Code sources for checkInexactFail

Tests for checkInexactFail variant are included with inexact values tests.

Here is the complete source code for this test suite.

You can also download the entire souce code as a zip file.

Complete test results are shown here.

_________________________________________________________________________________