mas01mj@732: package asunit.textui { mas01mj@732: import asunit.framework.Test; mas01mj@732: import asunit.framework.TestResult; mas01mj@732: mas01mj@732: import flash.display.MovieClip; mas01mj@732: import flash.display.StageAlign; mas01mj@732: import flash.display.StageScaleMode; mas01mj@732: import flash.events.Event; mas01mj@732: import flash.system.fscommand; mas01mj@732: import flash.utils.clearInterval; mas01mj@732: import flash.utils.describeType; mas01mj@732: import flash.utils.getTimer; mas01mj@732: import flash.utils.setInterval; mas01mj@732: import flash.utils.Timer; mas01mj@732: import flash.events.TimerEvent; mas01mj@732: import flash.display.DisplayObject; mas01mj@732: mas01mj@732: /** mas01mj@732: * The base class for ActionScript 3.0 test harness. mas01mj@732: * mas01mj@732: * The TestRunner should be extended by your mas01mj@732: * concrete runner for your project. mas01mj@732: * mas01mj@732: * If you're building a Flex application, you will need to mas01mj@732: * extend the FlexRunner mas01mj@732: * mas01mj@732: * Your concrete runner will usually look like the following: mas01mj@732: * mas01mj@732: * package { mas01mj@732: * import asunit.textui.TestRunner; mas01mj@732: * mas01mj@732: * public class MyProjectRunner extends TestRunner { mas01mj@732: * mas01mj@732: * public function MyProjectRunner() { mas01mj@732: * // start(clazz:Class, methodName:String, showTrace:Boolean) mas01mj@732: * // NOTE: sending a particular class and method name will mas01mj@732: * // execute setUp(), the method and NOT tearDown. mas01mj@732: * // This allows you to get visual confirmation while developing mas01mj@732: * // visual entities mas01mj@732: * start(AllTests, null, TestRunner.SHOW_TRACE); mas01mj@732: * } mas01mj@732: * } mas01mj@732: * } mas01mj@732: * mas01mj@732: * mas01mj@732: * @includeExample TestRunnerExample.as mas01mj@732: * mas01mj@732: * @see asunit.textui.FlexRunner mas01mj@732: * @see asunit.textui.AirRunner mas01mj@732: * @see asunit.textui.XMLResultPrinter mas01mj@732: **/ mas01mj@732: public class TestRunner extends MovieClip { mas01mj@732: public static const SUCCESS_EXIT:int = 0; mas01mj@732: public static const FAILURE_EXIT:int = 1; mas01mj@732: public static const EXCEPTION_EXIT:int = 2; mas01mj@732: public static const SHOW_TRACE:Boolean = true; mas01mj@732: protected var fPrinter:ResultPrinter; mas01mj@732: protected var startTime:Number; mas01mj@732: protected var result:TestResult; mas01mj@732: mas01mj@732: public function TestRunner() { mas01mj@732: configureListeners(); mas01mj@732: } mas01mj@732: mas01mj@732: private function configureListeners():void { mas01mj@732: addEventListener(Event.ADDED_TO_STAGE, addedHandler); mas01mj@732: addEventListener(Event.ADDED, addedHandler); mas01mj@732: } mas01mj@732: mas01mj@732: protected function addedHandler(event:Event):void { mas01mj@732: if (!stage) mas01mj@732: { mas01mj@732: return; mas01mj@732: } mas01mj@732: if(event.target === fPrinter) { mas01mj@732: stage.align = StageAlign.TOP_LEFT; mas01mj@732: stage.scaleMode = StageScaleMode.NO_SCALE; mas01mj@732: stage.addEventListener(Event.RESIZE, resizeHandler); mas01mj@732: resizeHandler(new Event("resize")); mas01mj@732: } mas01mj@732: } mas01mj@732: mas01mj@732: private function resizeHandler(event:Event):void { mas01mj@732: fPrinter.width = stage.stageWidth; mas01mj@732: fPrinter.height = stage.stageHeight; mas01mj@732: } mas01mj@732: mas01mj@732: /** mas01mj@732: * Starts a test run based on the TestCase or TestSuite provided. mas01mj@732: * mas01mj@732: * If a concrete TestCase is provided to the start method, mas01mj@732: * you can also provide the string name of a single test method to execute. mas01mj@732: * mas01mj@732: * This will run the TestCase setUp method, then mas01mj@732: * the test method name that was provided, and will not run tearDown. mas01mj@732: * mas01mj@732: * This is a great way to build visual components in isolation and verify that they mas01mj@732: * behave as expected. mas01mj@732: * mas01mj@732: * @example The start method can accept a concrete test case and test method name: mas01mj@732: * mas01mj@732: * start(MyTestCase, 'myTestMethod'); mas01mj@732: * mas01mj@732: * mas01mj@732: * @example The start method usually accepts a test suite that includes all of your mas01mj@732: * test methods. mas01mj@732: * mas01mj@732: * start(AllTests, null, TestRunner.SHOW_TRACE); mas01mj@732: * mas01mj@732: * mas01mj@732: * @see TestSuite mas01mj@732: */ mas01mj@732: public function start(testCase:Class, testMethod:String = null, showTrace:Boolean = false):TestResult { mas01mj@732: // fscommand("showmenu", "false"); mas01mj@732: try { mas01mj@732: var instance:Test; mas01mj@732: if(testMethod != null) { mas01mj@732: instance = new testCase(testMethod); mas01mj@732: } mas01mj@732: else { mas01mj@732: instance = new testCase(); mas01mj@732: } mas01mj@732: return doRun(instance, showTrace); mas01mj@732: } mas01mj@732: catch(e:Error) { mas01mj@732: throw new Error("Could not create and run test suite: " + e.getStackTrace()); mas01mj@732: } mas01mj@732: return null; mas01mj@732: } mas01mj@732: mas01mj@732: public function doRun(test:Test, showTrace:Boolean = false):TestResult { mas01mj@732: mas01mj@732: result = new TestResult(); mas01mj@732: mas01mj@732: if (test.getIsComplete()) mas01mj@732: return result; mas01mj@732: mas01mj@732: if(fPrinter == null) { mas01mj@732: setPrinter(new ResultPrinter(showTrace)); mas01mj@732: } mas01mj@732: else { mas01mj@732: fPrinter.setShowTrace(showTrace); mas01mj@732: } mas01mj@732: result.addListener(getPrinter()); mas01mj@732: startTime = getTimer(); mas01mj@732: test.setResult(result); mas01mj@732: test.setContext(this); mas01mj@732: test.addEventListener(Event.COMPLETE, testCompleteHandler); mas01mj@732: test.run(); mas01mj@732: return result; mas01mj@732: } mas01mj@732: mas01mj@732: private function testCompleteHandler(event:Event):void { mas01mj@732: var endTime:Number = getTimer(); mas01mj@732: var runTime:Number = endTime - startTime; mas01mj@732: getPrinter().printResult(result, runTime); mas01mj@732: } mas01mj@732: mas01mj@732: public function setPrinter(printer:ResultPrinter):void { mas01mj@732: if(fPrinter is DisplayObject && getChildIndex(fPrinter)) { mas01mj@732: removeChild(fPrinter); mas01mj@732: } mas01mj@732: mas01mj@732: fPrinter = printer; mas01mj@732: if(fPrinter is DisplayObject) { mas01mj@732: addChild(fPrinter); mas01mj@732: } mas01mj@732: } mas01mj@732: mas01mj@732: public function getPrinter():ResultPrinter { mas01mj@732: return fPrinter; mas01mj@732: } mas01mj@732: } mas01mj@732: }