jsunit_wrap.js File Reference


Detailed Description

A wrapper for JsUnit.

This file provides a wrapper for two extant JsUnit implementations:

This allows tests to be written which will run unchanged against either of the JsUnit implementations. There is a partial effort by the authors of those two projects (they are by no means hostile to each other), but that effort has not yet come to fruition, and in any event there are enough other issues with both of them to merit some separation, at least for now.

This file also provides its own built-in implementation, if neither JsUnit is available. It works in either a shell or a browser.

[ NOTE: there is also ECMAUnit, at http://kupu.oscom.org/download/ with a BSD license. It is command-line only. It has better implemented internals than Schaible JsUnit. We have not looked at it more closely at this time. ]

The wrapper determines which JsUnit implementation is in use through object detection.

It defines a javascript global called jum which represents the test environment. Methods on this object are used for assertions and any IO.

The sequence of script file loading should be as follows:

In the case of Hieatt JsUnit, the above scripts would be loaded via 'script' elements in an HTML page. In the case of Schaible JsUnit, the above scripts would be loaded on a javascript interpreter command line (such as via a "-f" option), or programmatically (for example by using a global load() function supplied by the environment).

We attempt to be well-behaved with respect to the underlying JsUnit implementation which is in use, so it should be possible to mix and match tests written to this API with ones using the implementation-specific API.

Some of the features of this wrapper are:

Determining what tests get run

For Hieatt JsUnit, if exposeTestFunctionNames is defined, we do nothing and rely on that. Otherwise we supply an implementation for that function. Either way, exposeTestFunctionNames is defined, so that Hieatt JsUnit's own attempts at reflection are never utilitized.

For Schaible JsUnit, if AllTests.suite is defined, we do nothing and rely on that. Otherwise we supply a definition.

If the jum.TEST_FUNCTION_NAMES is set, it is assumed to be a set of global function names of tests. If it is set, we do no reflection.

Test Declaration and Discovery

JUnit has a confusing set of terminology which JsUnit implementations retain (and are not to blame for). In JUnit

Schaible JsUnit mimics JUnit fairly closely, requiring the programming writing tests to subclass TestCase (using ECMAScript prototypes). There is also a TestSuite "class". In Schaible JsUnit, the TestSuite class does not extend TestCase. (There is some unnecessary confusion in the implementation concerning new() and constructors, but the idea is preserved.)

Schaible JsUnit does no reflection at the global level. It does do reflection-based discovery of test methods given a TestCase instance.

Hieatt JsUnit does not retain this terminology. It simply assumes there are any number of functions defined at the global level in some html page. A test "suite" is a collection of html pages.

Hieatt JsUnit attempts to use reflection to discover all test functions defined in an html page.

In our implementation, we introduce the notion of test "group", which is a collection of test functions. It is more akin to the JUnit "TestCase" in implmenetation, though given the name "TestCase", that is more often thought of as a single test.

We also have a single-level containment hierarchy, a collection of all test groups.

For us, a test "name" is systematically related to a test function name (in both directions).

Thus we draw a distinction between:

In Schaible JsUnit, we create a TestCase for each group. We then create a TestSuite which contains just that single TestCase.

Debug Output

There is a method jum.debug for debug output to be called from your tests.

You may or may not want any debug output from your library under test to be handled the same way. If so, it is up to you to override your own debug output functionality in your library under test, to call jum.debug when jum is defined.

Finding and Running Tests

Dependencies

If you want to be able to do deep comparison in assertEquals, an uneval implementation must be available. That means you need either burst.Lang.uneval, or you must be on a Mozilla javascript (which has Object.toSource()).

TODO

Todo:
deal with asserts done in async callbacks (See http://groups.yahoo.com/group/jsunit/message/144)

Issues

Hieatt assertTrue and assertFalse require that their argument is typeof boolean. Schaible assertTrue and assertFalse do an eval.

Neither implementation does deep equality in their assertEquals. That means it is difficult to test results against an Array or simple object like {a: 1, b: 2}.

Both are weak at reflection.

Some issues with both:

Some issues with Hieatt JsUnit:

Some issues with Schaible JsUnit:

Author:
Copyright 2003 Mark D. Anderson (mda@discerning.com)

Licensed under the Academic Free License 1.2 http://www.opensource.org/licenses/academic.php


Functions

public void debug (String line)
 display the String as debug output (if enabled by the test environment)

public void info (String line)
 display the String as info output (if enabled by the test environment)

public void warn (String line)
 display the String as warn output (if enabled by the test environment)

public void assertTrue (String message, Object obj)
 Assert that eval(obj) tests as true.

public void assertTrue (Object obj)
 Variant for 1 arg.

public void assertFalse (String message, Object obj)
 Assert that eval(obj) tests as false.

public void assertFalse (Object obj)
 Variant for 1 arg.

public void assertEquals (String message, Object expected, Object actual)
 Assert that expected and actual are equal.

public void assertEquals (Object expected, Object actual)
 Variant for 2 args.

public void runAll ()
 Run all tests.

public void untested (String funcname)
 Report that the specified test is not being tested (this is different from the test being tried and failed).

public Object pause (String funcname, String id, String desc)
 Indicate that this test is not over and will be continued asynchronously.

public void resume (String funcname, String id, Function func)
 Ask the test manager to resume execution for the named test.

public Boolean waitFor (String other_funcname, String other_id, String funcname, String id, Function func)
 Wait for the specified (other) test to have its resume done, then call this one.

public void init (Object scopeobj)
 Initializes the test runner.

public Boolean isFailureException (Object e)
 Return true if and only if the object is an exception indicating a test failure (vs.

public Boolean areTestsChosen ()
 Return true if and only if the tests are (somehow) already chosen, so that the wrapper should not try to determine and set them.

public void setTests (Object alltests)
 Set all the tests available.

public void reportAsync ()
 Should be called after all (synchronous) tests are run.


Variables

public RegExp TEST_FUNCTION_REGEXP
 By default match as 'test_' + groupname + '_' + testname.


Function Documentation

public Boolean areTestsChosen  ) 
 

Return true if and only if the tests are (somehow) already chosen, so that the wrapper should not try to determine and set them.

protected abstract.

public void assertEquals String  message,
Object  expected,
Object  actual
 

Assert that expected and actual are equal.

Out of the box, Hieatt does ===. Schaible uses == except when expected is a Regexp, and actual is a string, in which case it tests actual.match(expected).

Neither attempts a "deep" equality test, which makes comparison to Array or Object difficult.

If the function burst.Lang.uneval is not defined, we do nothing about all this, and just call the underlying function. If the function burst.Lang.uneval is available, it is applied to expected or actual if they have typeof 'object'. In this way, a basic "deep" comparison is possible.

public void assertFalse String  message,
Object  obj
 

Assert that eval(obj) tests as false.

Overloaded for 1 or 2 args (message is optional)

public void assertTrue String  message,
Object  obj
 

Assert that eval(obj) tests as true.

Overloaded for 1 or 2 args (message is optional). (We wrap Hieatt assertTrue and assertFalse to accomplish this semantic; natively it requires obj to be Boolean.)

public void init Object  scopeobj  ) 
 

Initializes the test runner.

Concrete method in the base class. Must be called after all tests scripts are loaded.

public Boolean isFailureException Object  e  ) 
 

Return true if and only if the object is an exception indicating a test failure (vs.

a test error). protected abstract.

public Object pause String  funcname,
String  id,
String  desc
 

Indicate that this test is not over and will be continued asynchronously.

Parameters:
funcname Test function name (possibly excluding 'test' or 'test_').
id A unique string within the test function. Can be null if the test will have only one continuation.
desc A description of what the expected continuation is doing, for use in any later error message

public void reportAsync  ) 
 

Should be called after all (synchronous) tests are run.

It first waits for completion of any outstanding asyncs (pause but no matching resume) for up to jum.DEFAULT_TIMEOUT_MILLIS.

public void resume String  funcname,
String  id,
Function  func
 

Ask the test manager to resume execution for the named test.

Parameters:
funcname Test function name (possibly excluding 'test' or 'test_').
id The value matching what was used in pause()
func The function to call now as the resumption.

public void runAll  ) 
 

Run all tests.

Only has to implemented in non-gui test managers.

public void setTests Object  alltests  ) 
 

Set all the tests available.

protected abstract.

Parameters:
alltests An associative array whose structure is currently not documented (see the source).

public void untested String  funcname  ) 
 

Report that the specified test is not being tested (this is different from the test being tried and failed).

By default, this is implemented as a particular message to jum.warn(), since this is not a concept supported in the JsUnit implementations (or JUnit, for that matter).

Parameters:
funcname Test function name (possibly excluding 'test' or 'test_').

public Boolean waitFor String  other_funcname,
String  other_id,
String  funcname,
String  id,
Function  func
 

Wait for the specified (other) test to have its resume done, then call this one.

Returns true if other is already done. Throws if other is never heard of (no previous pause call).


Generated on Fri Sep 2 01:14:40 2005 for ../build/tooldoc/JsTestManager/jsunit_wrap by doxygen 1.3.4