|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object com.cleancode.test.TestHarness
public class TestHarness
Provides a test harness for running unit and functional tests against Java objects.
TestHarness provides a flexible structure for exercising your individual Java classes or a collection of classes. You may instantiate a TestHarness inside your class (or more typically, inside a nested Test class inside your class), define a series of tests as a data structure, then execute the tests with this invocation:
TestHarness testHarness = new TestHarness(); testHarness.testList(testData);
An alternative approach that may be useful depending on how you organize
your files, is to have a central testing class whose testData
structure contains tests for a collection of classes rather than for just
a single class.
A third approach is to define the tests (testData
)
within each class, but execute them by invoking TestHarness
in a standalone mode, specifying one or more directories
to scan for class files and invoke the tests contained within. (TBD)
Let's first look at an example data structure. The numbers at the left are not part of the structure; they are just for this discussion.
# 1# Object[] testVector = # 2# { # 3# obj1, # 4# new Object[] { "getColor", # 5# "color", "green", # 6# }, # 7# "java.lang.Math", # 8# new Object[] { "max", # 9# new Object[] { "3", "-5" }, "3", #10# new Object[] { "3", "5" }, "5" #11# }, #12# new Object[] { "sqrt", #13# "2", "1.4142135623730951", #14# "4", "2", #15# "9", "3" #16# }, #17# new Object[] { "min", #18# new Object[] { "3", "5" }, "3" #19# } #20# settings, #21# new Object[] { "getProperty", #22# "item1", "1", #23# new Object[] { "item2", "default" }, "2222", #24# "item3", "-", #25# } #26# new ArrayList(), #27# new Object[] { "add", #28# "stuff", "true", #29# "null:java.lang.Object", "true" #30# }, #31# new Object[] { "add", #32# new Object[] { "1", "stuff" }, "[void]" #33# } #34# };
The data structure above may be passed to the testList
method and each test case will be executed.
For each test case TestHarness outputs one line, displaying
the test case, and indicating whether it passed, failed,
or encountered an error.
The testVector (line 1) is an array of Objects.
The Objects within may be either instance objects to test (lines 3, 20, 26),
lists of instance methods for those objects (lines 4, 21, 27, 31),
class names to test (line 7),
or lists of static methods for those classes (lines 8, 12, 17),
Once an object or class name occurs in the list,
all subsequent method lists will operate on that object or class.
In the example, the obj1
object has 1 such method list
following, while the java.lang.Math
class name has 3 such lists.
The BNF syntax for the testVector
is:
<testVector> ::= 'new Object [' { <testSpec> ',' } ']' <testSpec> ::= <Object> | <className> | <testCaseList> <testCaseList> ::= 'new Object[] {' <methodName> ',' { <args> ',' <result> ',' } '}' <args> ::= 'new Object[] {' { <arg> ',' } '}' | <arg> <arg> ::= <Object> | <qualifiedNull> <qualifiedNull> ::= '"null:' <className> '"' <result> ::= <Object> | <voidMarker> | 'null' <voidMarker> ::= '"[void]"' <className> ::= <String> <methodName> ::= <String>
"null:class"
. When dealing with methods generically,
the type of each argument must be known. The null value may
represent any type, so you must explicitly specify the type.
For example, to specify a null value for a Date argument,
use the string "null:java.util.Date".("3", new Foo())
.
That's easy, right? Perhaps too easy. When I say precisely, I mean
just that. If your method signature was instead an int argument
followed by an Object argument, then the argument list given
would be accepted by the compiler, but TestHarness has to do
a bit of extra work, because the Class object's getMethod
method requires an exact match.
TestHarness, then, tries getMethod with arguments of (int, Foo)
.
If it fails to find that, then it will look
for (int, Object)
, since all objects derive from Object.
Similarly, if TestHarness has identified an argument as a character
and that failed, then it will assume it is simply a one-character String,
and try again.
Also, non-integral numbers are first assumed to be of float type;
if a signature does not match, then it is converted to double.
That's as far as it goes; TestHarness does not check the full lineage
of an object to find a matching signature, so you may run into some
limitations here.VOID_METHOD_MARKER
in place of an expected value.
java.lang.String
itself, because of this facility.public
method.
--int vs long
--standalone mode, specifying a directory to process (as in Perl version).
Nested Class Summary | |
---|---|
class |
TestHarness.Counter
A basic counter object. |
static class |
TestHarness.Test
A standalone test class to exercise TestHarness. |
Field Summary | |
---|---|
static String |
VERSION
Current version of this class. |
static String |
VOID_METHOD_MARKER
String to use to indicate no return value expected. |
Constructor Summary | |
---|---|
TestHarness()
Creates a TestHarness object with no diagnostics. |
|
TestHarness(String[] args)
Creates a TestHarness object with the option
to display diagnostics. |
Method Summary | |
---|---|
static char |
charTester(int n,
boolean b)
A method used internally to test TestHarness (but it needs to be public to be accessible by TestHarness). |
boolean |
testList(Object[] testVector)
Executes the test suite specified by the supplied testVector . |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final String VERSION
public static final String VOID_METHOD_MARKER
Constructor Detail |
---|
public TestHarness()
TestHarness
object with no diagnostics.
public TestHarness(String[] args)
TestHarness
object with the option
to display diagnostics.
If the first argument is "-v" (for verbose), diagnostic
output will be displayed, indicated how tests are performed and analyzed.
args
- list of option stringsMethod Detail |
---|
public boolean testList(Object[] testVector)
testVector
.
See the introduction in this file for syntax of
the testVector
.
Each executed test will be displayed with a pass/fail indication.
At the end of the run, testList
displays a summary
including how many tests were executed and how many failed.
Note that a failure may be either an executed test whose result
does not match the expected result (marked as FAIL),
or an error (marked as ERR).
Successful tests are marked as OK.
Errors may arise from an invalid testVector
or from exceptions thrown when the target methods
themselves are executed.
The test report includes the class name and the class version
if the class has defined a VERSION variable.
testVector
- list of test cases to process
public static char charTester(int n, boolean b)
n
- integer flag; 0 forces return of 'a'b
- boolean flag; true forces return of 'a'
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
CleanCode Java Libraries | Copyright © 2001-2012 Michael Sorens - Revised 2012.12.10 |