blob: 74949637bbaa850228f34ad0c82b16b8b2e38185 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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.
//
////////////////////////////////////////////////////////////////////////////////
package testshim {
import org.apache.flex.reflection.MetaDataArgDefinition;
import org.apache.flex.reflection.MetaDataDefinition;
import org.apache.flex.reflection.MethodDefinition;
import org.apache.flex.reflection.TypeDefinition;
import org.apache.flex.reflection.describeType;
import flexunit.framework.Assert;
public class FlexJSUnitTestRunner {
public function FlexJSUnitTestRunner(testerClass:Class, notificationReceiver:Function) {
this.testerClass = testerClass;
this.callback = notificationReceiver;
prepare();
}
private var testerClass:Class;
private var callback:Function;
private var _testingName:String;
public function get testingName():String{
return _testingName;
}
private var _successCount:uint=0;
public function get successCount():uint {
return _successCount;
}
private var _failCount:uint=0;
public function get failCount():uint {
return _failCount;
}
private var _successfulAssertions:uint=0;
public function get successfulAssertions():uint {
return _successfulAssertions;
}
private var beforeClassFunc:Function;
private var afterClassFunc:Function;
private var setupFunc:MethodDefinition;
private var tearDownFunc:MethodDefinition;
private var testMethods:Array=[];
private function prepare():void{
var typeDef:TypeDefinition = describeType(testerClass);
_testingName = typeDef.name;
var staticMethods:Array = typeDef.staticMethods;
for each (var methodDef:MethodDefinition in staticMethods) {
var beforeClass:Array = methodDef.retrieveMetaDataByName("BeforeClass");
var afterClass:Array = methodDef.retrieveMetaDataByName("AfterClass");
if ( beforeClass.length ) {
if (beforeClassFunc!=null) throw new Error("BeforeClass used more than once in "+typeDef.qualifiedName);
beforeClassFunc = testerClass[methodDef.name];
}
if ( afterClass.length ) {
if (afterClassFunc!=null) throw new Error("AfterClass used more than once in "+typeDef.qualifiedName);
afterClassFunc = testerClass[methodDef.name];
}
}
var methods:Array = typeDef.methods;
for each (methodDef in methods) {
var beforeTests:Array = methodDef.retrieveMetaDataByName("Before");
var afterTests:Array = methodDef.retrieveMetaDataByName("After");
if ( beforeTests.length ) {
if (setupFunc!=null) throw new Error("Before used more than once in "+typeDef.qualifiedName);
setupFunc = methodDef;
}
if ( afterTests.length ) {
if (tearDownFunc!=null) throw new Error("After used more than once in "+typeDef.qualifiedName);
tearDownFunc = methodDef;
}
var test:Array = methodDef.retrieveMetaDataByName("Test");
if (test.length) {
testMethods.push(methodDef);
}
testMethods.sortOn("name");
}
if (testMethods.length == 0) {
throw new Error("Zero test methods detected in "+typeDef.qualifiedName+", check to make sure -keep-as3-metadata is configured");
}
}
private function begin():void {
if (beforeClassFunc!=null) beforeClassFunc();
}
public function runTests():void{
begin();
var testInstance:Object = new testerClass();
if (setupFunc!=null) {
testInstance[setupFunc.name]();
}
var i:uint=0, l:uint=testMethods.length;
for(;i<l;i++) {
runFlexJSTest(_testingName,testInstance,testMethods[i],callback);
}
if (tearDownFunc!=null) {
testInstance[tearDownFunc.name]();
}
end();
}
private function end():void{
if (afterClassFunc!=null) afterClassFunc();
}
private function runFlexJSTest(testClass:String,instance:Object,methodDef:MethodDefinition,callback:Function=null):void{
var methodName:String = methodDef.name;
trace('running test in '+testClass+":"+methodName);
var varianceMetas:Array = methodDef.retrieveMetaDataByName("TestVariance");
var method:Function = instance[methodName];
var preAssertCount:uint = Assert.assertionsMade;
var result:TestResult = new TestResult();
result.assertions = 0;
result.pass = true;
result.error = null;
result.testClass = testClass;
result.testMethod = methodName;
while (varianceMetas.length) {
var varianceMeta:MetaDataDefinition = varianceMetas.shift();
var varianceArgs:Array = varianceMeta.getArgsByKey("variance");
var i:uint=0, l:uint= varianceArgs.length;
if (l) {
result.hasVariance=true;
for(;i<l;i++) varianceArgs[i] = varianceArgs[i].value;
result.varianceTarget = varianceArgs.join(",");
}
if (result.hasVariance) {
var descriptionArgs:Array= varianceMeta.getArgsByKey("description");
if (descriptionArgs.length) result.varianceDescription = "";
while(descriptionArgs.length) {
var description:MetaDataArgDefinition = descriptionArgs.shift();
result.varianceDescription +=description.value;
if (descriptionArgs.length) result.varianceDescription += ", ";
}
}
}
//run the test method
try {
method();
} catch (e:Error) {
result.pass=false;
result.error = e.name+":" + e.message;
}
result.assertions = Assert.assertionsMade - preAssertCount;
if (preAssertCount == Assert.assertionsMade) {
result.warning = "WARNING: This test method appears to have zero Assertions";
}
if (result.pass) _successCount++;
else _failCount++;
_successfulAssertions += result.assertions;
if (callback!=null) {
callback(result);
}
}
}
}