JsUnit 1.3 |
![]() |
![]() |
JsUnit follows the scheme that all member variables are declared within this constructor. Afterwards all member functions are declared, using the name schema classname_memberfunctionname. All member functions are then added to the prototype of the class. This prevents naming conflicts in the global namespace. The first section within the constructor is used for the inheritance. Call a base class by using the call method of its constructor:
function ClassName( arg1, arg2 )
{
BaseClass.call( this, arg1, arg2 );
}
After calling the constructor you should initialize the member variables by assigning them a value:
this.mMember1 = 1; this.mMember2 = "yes";
After writing the constructor it is the time to define all member functions. Declare the function using the class name as prefix. Assign all functions afterwards to the prototype:
function ClassName_f1() {}
function ClassName_f2() {}
ClassName.prototype = new BaseClass();
ClassName.prototype.f1 = ClassName_f1;
ClassName.prototype.f2 = ClassName_f2;
The assignment of the methods is quite cumbersome for a big number of member functions and it is easy to forget one. Therefore the Function object has been enhanced with a new method glue that automates this assignment as long as the naming convention is honored:
function ClassName_f1() {}
function ClassName_f2() {}
ClassName.prototype = new BaseClass();
ClassName.glue();
It is no problem to overload a function that was already assigned in a the base class. Call the overloaded function using its apply or call method in the prototype of the constructor:
function ClassName_f1() { BaseClass.prototype.f1.apply( this, arguments ); } //... ClassName.prototype.f1 = ClassName_f1;
You may also define static member variables using a prototype definition:
ClassName.prototype.v1 = 1;
function ClassName( arg1, arg2 ) { BaseClass.call( this, arg1, arg2 ); } ClassName.prototype = new BaseClass(); ClassName.prototype.f1 = function ClassName_f1( arg1 ) { BaseClass.prototype.f1.call( this, arg1 ); } ClassName.prototype.f2 = function() { BaseClass.prototype.f2.apply( this, arguments ); } ClassName.prototype.v1 = 1;
The advantage of method f2
definition is, that the code is quite compact and keeps the global namespace clean. The disadvantage is that the function itself has no name and the call stack (if supported by the engine) will return an anonymous function call.
function InterfaceName() {} InterfaceName.prototype.f1 = function() {} InterfaceName.prototype.f2 = function( a, b ) {}
An interface definition may only define member functions, but no member variables. To ensure that a class fulfills this interface you call its function fulfills
ClassName()
{
}
//...
ClassName.prototype.f1 = ClassName_f1;
ClassName.prototype.f2 = ClassName_f2;
ClassName.fulfills( InterfaceName );
Writing unit tests you have to write at first test cases for your classes. The programming paradigm of eXtreme Programming demands writing your test cases first. Then you are able to program your class against the test case, so you know when you are ready. Anyway, writing a test case means deriving from class TestCase:
function SimpleTest(name) { TestCase.call( this, name ); }
Overload the setUp function if necessary:
function SimpleTest_setUp() { this.fValue1= 2; this.fValue2= 3; }
Add your test fixtures:
function SimpleTest_testDivideByZero() { var zero = 0; this.assertEquals( "Infinity", 8/zero ); }
You may also overload the tearDown function. To complete the class you have to assign the methods
In a final step you have to create a TestSuite out of all your test classes. Derive your own test suite from the TestSuite:
You may add as many test classes as you want or even other test suites. The test methods will automatically found if they follow the naming conventions.
/* JsUnit - a JUnit port for JavaScript Copyright (C) 1999,2000,2001,2002,2003,2006 Joerg Schaible Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ if( !this.JsUtil ) { if( this.WScript ) { var fso = new ActiveXObject( "Scripting.FileSystemObject" ); var file = fso.OpenTextFile( "../lib/JsUtil.js", 1 ); var all = file.ReadAll(); file.Close(); eval( all ); } else load( "../lib/JsUtil.js" ); eval( JsUtil.prototype.include( "../lib/JsUnit.js" )); eval( JsUtil.prototype.include( "ArrayTest.js" )); eval( JsUtil.prototype.include( "demo/Demo.js" )); eval( JsUtil.prototype.include( "demo/DemoTest.js" )); eval( JsUtil.prototype.include( "money/IMoney.js" )); eval( JsUtil.prototype.include( "money/Money.js" )); eval( JsUtil.prototype.include( "money/MoneyBag.js" )); eval( JsUtil.prototype.include( "money/MoneyTest.js" )); eval( JsUtil.prototype.include( "SimpleTest.js" )); } function AllTests() { TestSuite.call( this, "AllTests" ); } function AllTests_suite() { var suite = new AllTests(); suite.addTest( ArrayTestSuite.prototype.suite()); suite.addTest( MoneyTestSuite.prototype.suite()); suite.addTest( SimpleTestSuite.prototype.suite()); return suite; } AllTests.prototype = new TestSuite(); AllTests.prototype.suite = AllTests_suite; var args; if( this.WScript ) { args = new Array(); for( var i = 0; i < WScript.Arguments.Count(); ++i ) args[i] = WScript.Arguments( i ); } else if( this.arguments ) args = arguments; else args = new Array(); var result = TextTestRunner.prototype.main( args ); JsUtil.prototype.quit( result );
This file can also be included from HTML code using a script tag. See AllScripts.html that demonstrated this reuse.
JsUnit provides a special EmbeddedTextTestRunner that can act as special entry point for other applications embedding JsUnit. Such a TestRunner has a run method that takes an array of Strings as names of the tests to perform. The ideal combination is a TestCollector implementation that collects these names from the current scope. See as example:
var writer = new HTMLWriterFilter( JsUtil.prototype.getSystemWriter()); var printer = new ClassicResultPrinter( writer ); var runner = new EmbeddedTextTestRunner( printer ); var collector = new TestCaseCollector( this ); runner.run( collector.collectTests());
The EmbeddedTextTestRunner simply takes a ResultPrinter implementation as argument (here an implementation that writes HTML code into the document) and uses a TestCaseCollector to find all available TestCase implementations in the current scope. As alternative JsUnit provides also an AllTestsCollector and a TestSuiteColector.
Have a look at the Java code of the package to see how such a construct is used in combination with Rhino - a Java implementation of JavaScript - to generate XML for the various JUnit report generators:
final String xml = (String)context.evaluateString(scope, "" + "var stringWriter = new StringWriter();\n" + "var runner = new EmbeddedTextTestRunner(new XMLResultPrinter(stringWriter));\n" + "var collector = new AllTestsCollector(this);\n" + "runner.run(collector.collectTests());\n" + "stringWriter.get();\n", "AllTests", 1, null); writer.write(xml);
Most supported environments cannot share their test application. Therefore are a lot of AllTests*.* files part of the sample package. See the list below for all deliveries. Individual execution of the examples is available in the product specific documentation.
Files | Environment |
AllTests.html
| Any browser with a JavaScript implementation capable of exceptions
|
AllTests.vup
| Project for Microsoft Visual Interdev
|
AllTests.wsf
| Script for Windows Script Host. Run best with cscript
|
AllTestsBV AllTestsBV.jsp
| JavaScript Server Page of BroadVision's One-2-one server. Use the script AllTestsBV to start the ctxdriver for command line invocation.
|
AllTestsNS AllTestsNS.html
| Netscape SSJS application. The shell script uses jsac to compile the web application. The script generates a web file from the HTML source and the other used files.
|
AllTests.js
| JavaScript to use with the JavaScript shells. For the Mozilla shells use java -jar js.jar to run Rhino built from Java source or use jsshell resp. js to run SpiderMonkey built from C source. You may also use cscript for this file or kjscmd.
|
build.xml
| Apache Ant build file that runs the Ant Task for JsUnit tests with the help of Rhino. A test report is generated that can be processed by JUnitReport.
|
pom.xml
| Maven 2 project description file that runs the Maven 2 plugin for JsUnit tests with the help of Rhino. A test report is generated that can be processed by the Surefire Report plugin.
|
JsUnit © 1999, 2000, 2001, 2002, 2003, 2006, 2007 by Jörg Schaible
|
Generated on Fri Oct 19 23:10:41 2007 for JsUnit by doxygen 1.5.2
|