Program testing, part 1: the set-up.

From: R. Clayton <rclayton_at_monmouth.edu>
Date: Fri, 19 Feb 2010 10:30:09 -0500
In class yesterday I mentioned how important it is for you - or, better,
someone you trust - to test your code.  This is the first of a three-part
series of messages about a simple way to test your code.  Let me know if you
have any questions or comments.

I mostly use the JUnit testing framework ( junit.org ) to test my Java code,
but I also use a simpler testing scheme that uses nothing but java.  I'm going
to describe the simpler scheme here.

Let's suppose you've written a linked-list class:

  $ cat LinkedList.java
  public class
  LinkedList<E>
  implements LinkedSequence<E> {

    // blah blah blah

    }

  $

Now you want to test your class.  The testing scheme adds a main method to the
class you want to test (LinkedList in this case) and puts the testing code in
main.  Once you've done that, you can test your class by running it.

  Q: But what if the class C I want to test already has a main() method?

  A: There's a couple of ways to handle classes with existing main() methods.
  The first, and probably the best, way is to refactor your class so the main()
  method is in its own class.  Now class C has no main, and you can add your
  testing main.

  If, for whatever reason, you can't factor out main, you have to do something
  uglier: change main() to recognize a command-line argument, "-t" say.  When
  main() finds the command-line argument, it runs the testing code instead of
  doing what ever it usually does.

For example, suppose the linked-list class doesn't have a main() method; add
one:


  $ cat LinkedList.java
  public class
  LinkedList<E>
  implements LinkedSequence<E> {

    // blah blah blah

    public static void
    main(String args[]) {
      }

    // blah blah blah
    }

  $

In this case main() doesn't do anything;  we'll consider what to put in main()
in part 2.  Once a class has a main and compiles successfully, you can run the
class; that is, call its main method():

  $ javac -classpath pa1.jar:. LinkedList

  $ java -classpath pa1.jar:. LinkedList

Now suppose that the linked-list class already has a main that can't be
refactored into a separate class:

  $ cat LinkedList.java
  public class
  LinkedList<E>
  implements LinkedSequence<E> {

    // blah blah blah

    public static void
    main(String args[]) {
      System.out.println("Do important stuff.");
      }

    // blah blah blah
    }

  $

Change main() to look through the command-line arguments for the testing
option, and run the tests if it finds it:

  $ cat LinkedList.java
  public class
  LinkedList<E>
  implements LinkedSequence<E> {

    // blah blah blah

    public static void
    main(String args[]) {
      if ((args.length > 0) && args[0].equals("-t"))
	System.out.println("Do testing.");
      else
	System.out.println("Do important stuff.");
      }

    // blah blah blah
    }

  $

This example assumes the non-testing main() doesn't use any command-line
arguments.  If it does, the search for the testing option will be more
complicated, but it can probably be folded in with the other command-line
processing.

  $ javac -classpath pa1.jar:. LinkedList.java

  $ java -classpath pa1.jar:. LinkedList
  Do important stuff.

  $ java -classpath pa1.jar:. LinkedList -t
  Do testing.

  $

That's it for the simple testing framework; you can add it to each class you
want to test (which should be every class you write).

  Q: Really?  There won't be any trouble with having multiple main() methods?

  A: No.  Unlike other, more conventional languages you may know, java doesn't
  require that there only be one main() defined.  Instead, you tell the JVM
  which class's main() method you want it to run, and execution proceeds from
  there. (And if that class doesn't define a main() method, you'll get the
  usual 

    Exception in thread "main" java.lang.NoSuchMethodError: main

  explosion.)
Received on Fri Feb 19 2010 - 10:30:17 EST

This archive was generated by hypermail 2.2.0 : Fri Feb 19 2010 - 20:02:55 EST