JXPUnit User Guide
Version 1.1.0
April 17, 2002
Author: Sunny Liu
Email: sunnyliu2@yahoo.com
1.
Introduction
JXPUnit is an Apache ANT like Java Programming Unit Test Tool. It takes unit test instructions XML file (test descriptor) as input, and reports back test result to specified target (Log file, Swing GUI JtextArea, console etc.).
Ps; this user guide is not complete yet, if you have any question about JXPUnit, Please drop me an email. Thanks.
Microsoft.NET version (XPUnit.NET) here.
· Test Class with complicated constructor or create an instance from factory Class.
· Dynamic load class from CLASSPATH you specified in Test Descriptor file, which is not in your system CLASSPATH.
· Accept complicated custom data type.
· Integrated with Test Descriptor Editor in one GUI environment.
· Filter Unit Test Result dynamically.
· Supports nested custom data type.
· Supports multiple test cases.
· Supports Setup and Teardown.
2.
How to use JXPUnit
Recent version of JXPUnit has been refactored for easier adding new function to it. You can use JXPUnit either in console mode or Swing Gui mode.
1. Console mode’s command
User# java com.sunny.jxp.core.JXPUnit [options]
Or
C:> java com.sunny.jxp.core.JXPUnit [options]
Use following command for console command line options help
User# java com.sunny.jxp.core.JXPUnit -help
Or
C:> java com.sunny.jxp.core.JXPUnit –help
2. Swing GUI mode
User# java com.sunny.jxp.gui.JXPGui
Or
C:> java com.sunny.jxp.gui.JXPGui
3.
How to use JXPUnit in GUI
Mode
It works much like Microsoft Office’s menu and tool bar. It support unlimited undo and redo feature, as well as Cut, Copy and Paste. Here is a screen shot of JXPUnit in GUI mode
1)
Open Test Descriptor
There are a few approachs to open test descriptor.
a) File menu -> Open Test Suite
b) Toolbar Open Button.
c) From file menu’s most recent accessed file list.
d) Type test descriptor’s full file path or directory name in test descriptor field on tool bar. Then click “GO” button.
2) Run Unit Test
1) Run menu -> Run Test Suite
2) Toolbar -> Run Button
3)
Filter Output
Format menu-> Result Information
4) Create New Test Descriptor
1) File menu ->New Test Suite
2) Toolbar -> New Button
5) Using Short-cut keys and Edit
menus
Both Edit menu and Editor pane’s popup menu will help you create test descriptor quickly and easily.
Popup Menu
4.
How to write a test descriptor
Test descriptor is a well-formed XML file. It has an only root element <test-suite>. Test-suite can contains multiple test-case element. Each test-case stands for a Java class that you want to be tested. Please refer section 5 for elements reference. I will write some example here and show how does it works.
Example 1,
Target Class:
package com.sunny.jxp.test;
public class Testee1
{
public void hello()
{
System.out.println("Hello World");
}
}
Test Descriptor:
<?xml version="1.0" encoding="utf-8" ?>
<test-suite>
<test-case class="com.sunny.jxp.test.Testee1">
<test-runner>
<test-method name="hello" />
</test-runner>
</test-case>
</test-suite>
Result: (report-level 2)
com.sunny.jxp.core.TestInputHandler Test Descriptor loaded successfully.
----------------------------------------- Test Suite ------------------------------------------
Test Case 1 Target ->com.sunny.jxp.test.Testee1
com.sunny.jxp.test.Testee1 function test started.
Method : hello started
Method : hello return type [void]
Method : hello return value [void]
Method : hello completed successfully
Mehtod : hello time ellaps [0] ms
com.sunny.jxp.test.Testee1 tested method count = 1
com.sunny.jxp.test.Testee1 succeed method count = 1
com.sunny.jxp.test.Testee1 failed method count = 0
com.sunny.jxp.test.Testee1 time ellapes [10] ms
com.sunny.jxp.test.Testee1 function test ended.
Test Suite tested testcase count = 1
Test Suite succeed testcase count = 1
Test Suite failed testcase count = 0
Example 2:
// ShyClass.java
package com.sunny.jxp.test;
public class ShyClass
{
private String name = null;
public ShyClass(String name, ShyClassFactory factory) throws Exception
{
if ( factory.identify() == false ) throw new Exception("You are not allowed to create me.");
this.name = name;
}
public void whatIsYourName()
{
System.out.println("My name is " + name);
}
}
// ShyClassFactory.java
package com.sunny.jxp.test;
public class ShyClassFactory
{
private boolean id = false;
private void changeID()
{
id = true;
}
public boolean identify()
{
return id;
}
public ShyClass getShyClass(String name) throws Exception
{
ShyClassFactory scf = new ShyClassFactory();
scf.changeID();
ShyClass sc = new ShyClass(name, scf);
return sc;
}
}
Test Descriptor:
<?xml version="1.0" encoding="utf-8" ?>
<test-suite>
<test-case class="com.sunny.jxp.test.ShyClass">
<test-constructor source="com.sunny.jxp.test.ShyClassFactory" >
<test-method name="getShyClass" isStatic="true">
<param>
<type>java.lang.String</type>
<value>SHYCLASSNAME</value>
</param>
</test-method>
</test-constructor>
<test-runner>
<test-method name="whatIsYourName">
</test-method>
</test-runner>
</test-case>
</test-suite>
Test Result:
com.sunny.jxp.core.TestInputHandler Test Descriptor loaded successfully.
----------------------------------------- Test Suite ------------------------------------------
Test Case 1 Target ->com.sunny.jxp.test.ShyClass
com.sunny.jxp.test.ShyClass function test started.
Method : whatIsYourName started
Method : whatIsYourName return type [void]
Method : whatIsYourName return value [void]
Method : whatIsYourName completed successfully
Mehtod : whatIsYourName time ellaps [0] ms
com.sunny.jxp.test.ShyClass tested method count = 1
com.sunny.jxp.test.ShyClass succeed method count = 1
com.sunny.jxp.test.ShyClass failed method count = 0
com.sunny.jxp.test.ShyClass time ellapes [20] ms
com.sunny.jxp.test.ShyClass function test ended.
Test Suite tested testcase count = 1
Test Suite succeed testcase count = 1
Test Suite failed testcase count = 0
Example 3:
//SingletonClass.java
package com.sunny.jxp.test;
public class SingletonClass
{
private static SingletonClass sc = new SingletonClass();
protected SingletonClass()
{
}
public static SingletonClass newInstance()
{
return sc;
}
public synchronized void testMe(String testString)
{
System.out.println("FROM SingletonClass.testMe: " + testString);
}
}
//Testee.java
package com.sunny.jxp.test;
import java.io.PrintStream;
public class Testee
{
String name;
public String displayString = null;
public int displayInt = 0;
public Testee()
{
name = null;
}
public Testee(double d, int i)
{
this();
}
public Testee(String s)
{
name = null;
name = s;
}
public void display() throws RuntimeException
{
if (displayString == null || displayInt == 0 ){
throw new RuntimeException("Uninitialized Exception.");
}else{
System.out.println("displayString = " + displayString);
System.out.println("displayInt = " + displayInt);
}
}
public int intAddition(int i, int j)
{
return i + j;
}
public double doubleAddition(double d, int i)
{
return (d + i);
}
public double doubleAdditionWronng(double d, int i)
{
return (d + i + 1);
}
public String concateString(String s, String s1)
{
return s + s1;
}
public void customTypeMethod(MyType mytype)
{
System.out.print("Method with custom type parameter: >> name :");
System.out.println(mytype.name);
System.out.print("Method with custom type parameter: >> age :");
System.out.println(mytype.age);
}
public boolean boolMethod(boolean flag)
{
return !flag;
}
}
Test Descriptor:
<?xml version="1.0" encoding="utf-8" ?>
<test-suite log="C:/ret.log">
<classpath location="c:\target\target.jar"/>
<test-case class="com.sunny.jxp.test.SingletonClass">
<test-constructor>
<!--<param>
<type>java.lang.String</type>
<value>Hello world</value>
</param>-->
<test-method name="newInstance" isStatic="true" />
</test-constructor>
<test-runner>
<test-method name="testMe">
<param>
<type>java.lang.String</type>
<value>Hello world</value>
</param>
</test-method>
</test-runner>
</test-case>
<test-case class="com.sunny.jxp.test.Testee">
<test-constructor>
<param>
<type>java.lang.String</type>
<value>Hello world</value>
</param>
</test-constructor>
<test-runner>
<test-method name="intAddition">
<param>
<type>java.lang.Integer</type>
<value>10</value>
</param>
<param>
<type>java.lang.Integer</type>
<value>13</value>
</param>
</test-method>
<test-method name="concateString">
<param>
<type>java.lang.String</type>
<value>String1</value>
</param>
<param>
<type>java.lang.String</type>
<value>String2</value>
</param>
<test-return>
<param>
<type>java.lang.String</type>
<value>String1String2</value>
</param>
<condition>eq</condition>
</test-return>
</test-method>
</test-runner>
</test-case>
<test-case class="com.sunny.jxp.test.Testee">
<test-setup>
<public-field name="displayString">
<param>
<type>java.lang.String</type>
<value>Display me</value>
</param>
</public-field>
<public-field name="displayInt">
<param>
<type>java.lang.Integer</type>
<value>20</value>
</param>
</public-field>
</test-setup>
<test-runner>
<test-method name="intAddition">
<param>
<type>java.lang.Integer</type>
<value>10</value>
</param>
<param>
<type>java.lang.Integer</type>
<value>13</value>
</param>
</test-method>
<test-method name="display" />
</test-runner>
<test-teardown>
<public-field name="displayString" >
<param>
<type>java.lang.String</type>
</param>
</public-field>
<public-field name="displayInt">
<param>
<type>java.lang.Integer</type>
<value>0</value>
</param>
</public-field>
</test-teardown>
</test-case>
</test-suite>
Test Result:
com.sunny.jxp.core.TestInputHandler Test Descriptor loaded successfully.
----------------------------------------- Test Suite ------------------------------------------
Test Case 1 Target ->com.sunny.jxp.test.SingletonClass
com.sunny.jxp.test.SingletonClass function test started.
Method : testMe started
Method : testMe return type [void]
Method : testMe return value [void]
Method : testMe completed successfully
Mehtod : testMe time ellaps [0] ms
com.sunny.jxp.test.SingletonClass tested method count = 1
com.sunny.jxp.test.SingletonClass succeed method count = 1
com.sunny.jxp.test.SingletonClass failed method count = 0
com.sunny.jxp.test.SingletonClass time ellapes [10] ms
com.sunny.jxp.test.SingletonClass function test ended.
Test Case 2 Target ->com.sunny.jxp.test.Testee
com.sunny.jxp.test.Testee function test started.
Method : intAddition started
Method : intAddition return type [int]
Method : intAddition return value [23]
Method : intAddition completed successfully
Mehtod : intAddition time ellaps [0] ms
Method : concateString started
Mehtod : concateString return type [java.lang.String]
Method : concateString return value [String1String2]
Method : concateString completed successfully
Mehtod : concateString time ellaps [0] ms
com.sunny.jxp.test.Testee tested method count = 2
com.sunny.jxp.test.Testee succeed method count = 2
com.sunny.jxp.test.Testee failed method count = 0
com.sunny.jxp.test.Testee time ellapes [20] ms
com.sunny.jxp.test.Testee function test ended.
Test Case 3 Target ->com.sunny.jxp.test.Testee
com.sunny.jxp.test.Testee function test started.
Method : intAddition started
Method : intAddition return type [int]
Method : intAddition return value [23]
Method : intAddition completed successfully
Mehtod : intAddition time ellaps [0] ms
Method : display started
Method : display return type [void]
Method : display return value [void]
Method : display completed successfully
Mehtod : display time ellaps [-10] ms
com.sunny.jxp.test.Testee tested method count = 2
com.sunny.jxp.test.Testee succeed method count = 2
com.sunny.jxp.test.Testee failed method count = 0
com.sunny.jxp.test.Testee time ellapes [20] ms
com.sunny.jxp.test.Testee function test ended.
Test Suite tested testcase count = 3
Test Suite succeed testcase count = 3
Test Suite failed testcase count = 0
Example 5: Dynamic Class path
//LoaderTestClass1.java
package test;
public class LoaderTestClass1
{
public LoaderTestClass1(){};
public void hello()
{
System.out.println("Hello World from class 1");
}
public String toString()
{
return ("Hello, I am LoaderTestClass1.");
}
}
//LoaderTestClass.java
package test;
public class LoaderTestClass
{
public LoaderTestClass(){};
public void hello(LoaderTestClass1 ltc1)
{
if(ltc1!=null) ltc1.hello();
else
System.out.println("Hello World from LoaderTestClass");
}
public String toString()
{
return ("Hello, I am LoaderTestClass.");
}
}
Test Descriptor:
<?xml version="1.0" encoding="utf-8" ?>
<test-suite>
<test-case class="test.LoaderTestClass">
<classpath location="c:\Projects\tp" />
<test-runner>
<test-method name="hello">
<custom-type type="test.LoaderTestClass1"></custom-type>
</test-method>
</test-runner>
</test-case>
</test-suite>
Result (Full Detail ):
com.sunny.jxp.core.TestInputHandler Test Descriptor loaded successfully.
----------------------------------------- Test Suite ------------------------------------------
Test Case 1 Target ->test.LoaderTestClass
test.LoaderTestClass function test started.
Method : hello started
Method : hello return type [void]
Method : hello return value [void]
Method : hello completed successfully
Mehtod : hello time ellaps [0] ms
Method :hello Standard Output-> Hello World from class 1
test.LoaderTestClass tested method count = 1
test.LoaderTestClass succeed method count = 1
test.LoaderTestClass failed method count = 0
test.LoaderTestClass time ellapes [30] ms
test.LoaderTestClass function test ended.
Test Suite tested testcase count = 1
Test Suite succeed testcase count = 1
Test Suite failed testcase count = 0
5.
Test Descriptor Elements/Attributes reference
Dynamic class path loading are still under test. It expected to be available in next a few days. (Completed)
Convention:
0..* means zero or more
0..1 zero or one
1..* one or more
1 at least one is required
[], or other either one is required
[], with option either one in brack with or without option
test-suite |
Root Element |
||
Attributes |
name |
String |
Name of this test suite |
log |
String |
Full path to log file |
|
report-level |
int |
|
|
verbose |
boolean |
|
|
Sub Element |
classpath(0..*), test-case(1..*) |
Element test-case
test-case |
A test case against a Java class. Child of test-suite. |
||
Attributes |
class |
String |
Name of class of this test case against to. |
Sub Element |
classpath(0..*), test-constructor(0..1), test-setup(0..1), test-runner(1), test-teardown(0..1) |
Element classpath
classpath |
Global or specific test-case’s class path |
||
Attributes |
location |
String |
semicolon(windows)/colon(unix or linux) separated string for classpath |
Sub Element |
|
Element test-constructor
test-constructor |
A constructor used to instantiate test-case’s class. without a test-constructor, JXPUnit will use Java Object Default No parameter constructor to instantiate class. |
||
Attributes |
source |
String |
If this test-case’s class is getting from other class. source Attribute specifys which class is. |
Sub Element |
[custome-type(0..*), param(0..*)], or test-method(0..1) |
Element test-setup
test-setup |
Setup test-case public field and some initial method calls |
||
Attributes |
|
|
|
Sub Element |
public-field(0..*), test-method(0..*) |
Element test-teardown
test-teardown |
reset test-case public field and some clean method calls |
||
Attributes |
|
|
|
Sub Element |
public-field(0..*), test-method(0..*) |
Element test-runner
test-runner |
A collection of test-method elements that will be tested against. |
||
Attributes |
|
|
|
Sub Element |
test-method(1..*) |
test-method |
Stands for a definition of a method of test-case’s class |
||
Attributes |
name |
String |
Name of this test method |
isStatic |
boolean |
Is this a static public method |
|
Sub Element |
custom-type(0..*), param(0..*), test-return(0..1) |
custom-type |
Stands for a non-standard java type in java.lang package |
||
Attributes |
type |
String |
Java type of this parameter |
source |
String |
Source class name, getting this parameter instance from this source class. it require a test-method present in sub element. |
|
Sub Element |
[custom-type(0..*), param(0..*)], or test-method(1) |
Element param
param |
Stands for a java default type parameter for test-method or test-constructor or public-field , that is exist in java.lang package. |
||
Attributes |
|
|
|
Sub Element |
type(1), value(1) |
Element public-field
public-field |
Represents a public field in test-case’s class (not recommended, you shoud use setter/getter accessor method to do so). |
||
Attributes |
name |
String |
Name of this field in test-case’s class |
Sub Element |
custom-type(1), or param(1) |
Element type
type |
Java type which exists in java.lang package. |
||
Attributes |
isArray |
boolean |
Array of this type(default false) |
isWrapper |
boolean |
Exactly type of primitive type parameter. (default true) |
|
Sub Element |
Text string represents a default Java type in java.lang package java.lang.String java.lang.StringBuffer java.lang.Integer java.lang.Long java.lang.Double java.lang.Float java.lang.Byte java.lang.Short java.lang.Boolean java.lang.Character |
Element value
value |
Value of specific default paramter represents in text string. |
||
Attributes |
delimiter |
String |
Only need for array type(not implemented yet) |
Sub Element |
Text string, array may represents in comma separated fashion or with delimiter in specified attribute. |
Element test-return
test-return |
Expected return from a method under test. |
||
Attributes |
|
|
|
Sub Element |
[custom-type(1), or param(1)], with condition(0..1) |
Element condition
condition |
JXPUnit use it to compare returned result with expected result. |
||
Attributes |
|
|
|
Sub Element |
Text string representation of compare condition eq, equals ------ compare equals or not lt, less than ----- less than(not implemented yet) gt great than ---- great than(not implemented yet) lteq ----- less than equals(not implemented yet) gteq ----- great than equals(not implemented yet) default is NO ACTION, does not compare at all. |