asunit4 4.2.2.pre → 4.2.3.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. data/Gemfile.lock +26 -0
  2. data/bin/AsUnit-4.1.2.swc +0 -0
  3. data/bin/AsUnit-4.2.3.pre.swc +0 -0
  4. data/bin/AsUnitRunner.swf +0 -0
  5. data/bin/Flex4AsUnitRunner.swf +0 -0
  6. data/build.xml +42 -2
  7. data/lib/SwiftSuspenders-v1.5.1.swc +0 -0
  8. data/lib/flexUnitTasks.jar +0 -0
  9. data/pkg/sprout-asunit4-library-4.1.2.gem +0 -0
  10. data/rakefile.rb +4 -1
  11. data/sprout/lib/asunit4.rb +1 -1
  12. data/src/asunit/asserts/assertMatches.as +6 -0
  13. data/src/asunit/asserts/assertThrowsWithMessage.as +5 -0
  14. data/src/asunit/core/AsUnitCore.as +42 -88
  15. data/src/asunit/core/FlashBuilderCore.as +2 -2
  16. data/src/asunit/core/FlashDevelopCore.as +1 -1
  17. data/src/asunit/core/FlexUnitCICore.as +17 -0
  18. data/src/asunit/core/TextCore.as +36 -54
  19. data/src/asunit/framework/Assert.as +76 -11
  20. data/src/asunit/framework/Async.as +1 -1
  21. data/src/asunit/framework/IResult.as +1 -6
  22. data/src/asunit/framework/IRunListener.as +0 -3
  23. data/src/asunit/framework/IRunner.as +0 -3
  24. data/src/asunit/framework/IRunnerFactory.as +3 -3
  25. data/src/asunit/framework/ITestListener.as +1 -2
  26. data/src/asunit/framework/Method.as +82 -80
  27. data/src/asunit/framework/Result.as +3 -24
  28. data/src/asunit/framework/RunnerFactory.as +13 -34
  29. data/src/asunit/framework/SuiteIterator.as +28 -22
  30. data/src/asunit/framework/TestCase.as +8 -3
  31. data/src/asunit/printers/FlashBuilderPrinter.as +25 -83
  32. data/src/asunit/printers/FlashDevelopPrinter.as +1 -2
  33. data/src/asunit/printers/FlexUnitCIPrinter.as +181 -0
  34. data/src/asunit/printers/TextPrinter.as +17 -46
  35. data/src/asunit/printers/XMLPrinter.as +127 -0
  36. data/src/asunit/runners/LegacyRunner.as +6 -1
  37. data/src/asunit/runners/SuiteRunner.as +30 -66
  38. data/src/asunit/runners/TestRunner.as +90 -255
  39. data/test/AllTests.as +9 -4
  40. data/test/AsUnitCIRunner.as +18 -0
  41. data/test/AsUnitRunner.as +2 -0
  42. data/test/AsUnitRunnerCS3.fla +0 -0
  43. data/test/asunit/core/AsUnitCoreTest.as +33 -15
  44. data/test/asunit/framework/AssertEqualsArraysIgnoringOrderTest.as +14 -0
  45. data/test/asunit/framework/AssertThrowsWithMessageTest.as +50 -0
  46. data/test/asunit/framework/AsyncTest.as +0 -4
  47. data/test/asunit/framework/ProceedOnEventTest.as +1 -2
  48. data/test/asunit/framework/ResultObserverTest.as +61 -0
  49. data/test/asunit/framework/RunnerFactoryTest.as +7 -9
  50. data/test/asunit/framework/VisualTestCaseTest.as +2 -26
  51. data/test/asunit/printers/FlashBuilderPrinterTest.as +18 -0
  52. data/test/asunit/printers/XMLPrinterTest.as +131 -0
  53. data/test/asunit/runners/LegacyRunnerTest.as +4 -4
  54. data/test/asunit/runners/SuiteRunnerTest.as +10 -7
  55. data/test/asunit/runners/TestRunnerAsyncMethodTest.as +9 -7
  56. data/test/asunit/runners/TestRunnerErrorMethodTest.as +1 -1
  57. data/test/asunit/runners/TestRunnerExpectsErrorTest.as +2 -2
  58. data/test/asunit/runners/TestRunnerExpectsErrorWithMessageTest.as +125 -0
  59. data/test/asunit/runners/TestRunnerIgnoredMethodTest.as +2 -3
  60. data/test/asunit/runners/TestRunnerTest.as +4 -27
  61. data/test/asunit/support/{CustomTestRunner.as → CustomSuiteRunner.as} +7 -3
  62. data/test/asunit/support/InjectionVerification.as +2 -30
  63. data/test/asunit/support/SuiteWithCustomRunner.as +1 -1
  64. data/vendor/as3injection/org/swiftsuspenders/InjectionConfig.as +78 -0
  65. data/vendor/as3injection/org/swiftsuspenders/InjectionType.as +16 -0
  66. data/vendor/as3injection/org/swiftsuspenders/Injector.as +376 -0
  67. data/vendor/as3injection/org/swiftsuspenders/InjectorError.as +17 -0
  68. data/vendor/as3injection/org/swiftsuspenders/Reflector.as +95 -0
  69. data/vendor/as3injection/org/swiftsuspenders/getConstructor.as +33 -0
  70. data/vendor/as3injection/org/swiftsuspenders/injectionpoints/ConstructorInjectionPoint.as +94 -0
  71. data/vendor/as3injection/org/swiftsuspenders/injectionpoints/InjectionPoint.as +35 -0
  72. data/vendor/as3injection/org/swiftsuspenders/injectionpoints/MethodInjectionPoint.as +122 -0
  73. data/vendor/as3injection/org/swiftsuspenders/injectionpoints/NoParamsConstructorInjectionPoint.as +24 -0
  74. data/vendor/as3injection/org/swiftsuspenders/injectionpoints/PostConstructInjectionPoint.as +52 -0
  75. data/vendor/as3injection/org/swiftsuspenders/injectionpoints/PropertyInjectionPoint.as +62 -0
  76. data/vendor/as3injection/org/swiftsuspenders/injectionresults/InjectClassResult.as +33 -0
  77. data/vendor/as3injection/org/swiftsuspenders/injectionresults/InjectOtherRuleResult.as +34 -0
  78. data/vendor/as3injection/org/swiftsuspenders/injectionresults/InjectSingletonResult.as +43 -0
  79. data/vendor/as3injection/org/swiftsuspenders/injectionresults/InjectValueResult.as +33 -0
  80. data/vendor/as3injection/org/swiftsuspenders/injectionresults/InjectionResult.as +26 -0
  81. metadata +44 -19
  82. data/bin/AsUnit-4.2.1.pre.swc +0 -0
  83. data/bin/AsUnit-4.2.2.pre.swc +0 -0
  84. data/src/asunit/framework/CallbackBridge.as +0 -175
  85. data/src/asunit/framework/ITestResult.as +0 -21
  86. data/src/asunit/framework/InjectionDelegate.as +0 -96
  87. data/src/asunit/framework/MessageBridge.as +0 -24
  88. data/src/asunit/framework/TestObserver.as +0 -12
  89. data/test/asunit/framework/CallbackBridgeTest.as +0 -73
  90. data/test/asunit/framework/InjectionDelegateTest.as +0 -79
  91. data/test/asunit/support/AnnotatedSubClass.as +0 -18
  92. data/test/asunit/support/AnnotatedSuperClass.as +0 -15
  93. data/test/asunit/support/FakeRunner.as +0 -32
  94. data/test/asunit/support/InjectTimeoutOnAsync.as +0 -14
  95. data/test/asunit/support/TestForFakeRunner.as +0 -14
@@ -17,28 +17,31 @@ package asunit.printers {
17
17
  import flash.text.TextFormat;
18
18
  import flash.utils.getQualifiedClassName;
19
19
  import flash.utils.getTimer;
20
- import asunit.framework.CallbackBridge;
21
20
 
22
21
  public class TextPrinter extends Sprite implements IRunListener {
23
- public static var LOCAL_PATH_PATTERN:RegExp = /([A-Z]:\\[^\/:\*\?<>\|]+\.\w{2,6})|(\\{2}[^\/:\*\?<>\|]+\.\w{2,6})/g;
24
- public static var BACKGROUND_COLOR:uint = 0x333333;
25
- public static var DEFAULT_HEADER:String = "AsUnit 4.0 by Luke Bayes, Ali Mills and Robert Penner\n\nFlash Player version: " + Capabilities.version
26
- public static var FONT_SIZE:int = 12;
27
- public static var TEXT_COLOR:uint = 0xffffff;
22
+ public static const LOCAL_PATH_PATTERN:RegExp = /([A-Z]:\\[^\/:\*\?<>\|]+\.\w{2,6})|(\\{2}[^\/:\*\?<>\|]+\.\w{2,6})/g;
23
+ public static const DEFAULT_BACKGROUND_COLOR:uint = 0x333333;
24
+ public static const DEFAULT_HEADER:String = "AsUnit 4.0 by Luke Bayes, Ali Mills and Robert Penner\n\nFlash Player version: " + Capabilities.version
25
+ public static const DEFAULT_FOOTER:String = "";
26
+ public static const DEFAULT_FONT_SIZE:int = 12;
27
+ public static const DEFAULT_PERFORMANCE_COUNT:int = 10;
28
+ public static const DEFAULT_TEXT_COLOR:uint = 0xffffff;
28
29
 
29
- public var backgroundColor:uint = BACKGROUND_COLOR;
30
+ public var header:String = DEFAULT_HEADER;
31
+ public var footer:String = DEFAULT_FOOTER;
32
+ public var backgroundColor:uint = DEFAULT_BACKGROUND_COLOR;
33
+ public var textColor:uint = DEFAULT_TEXT_COLOR;
30
34
  public var displayPerformanceDetails:Boolean = true;
31
- public var localPathPattern:RegExp;
32
- public var textColor:uint = TEXT_COLOR;
33
35
  public var traceOnComplete:Boolean = true;
36
+ public var hideLocalPaths:Boolean = false;
37
+ public var localPathPattern:RegExp = LOCAL_PATH_PATTERN;
38
+ public var performanceCount:int = DEFAULT_PERFORMANCE_COUNT;
34
39
 
35
40
  protected var textDisplay:TextField;
36
41
 
37
42
  private var backgroundFill:Shape;
38
43
  private var dots:Array;
39
44
  private var failures:Array;
40
- private var footer:String;
41
- private var header:String;
42
45
  private var ignores:Array;
43
46
  private var resultBar:Shape;
44
47
  private var resultBarHeight:uint = 3;
@@ -48,34 +51,6 @@ package asunit.printers {
48
51
  private var testTimes:Array;
49
52
  private var warnings:Array;
50
53
 
51
- /**
52
- * The bridge provides the connection between the printer
53
- * and the Runner(s) that it's interested in.
54
- *
55
- * Generally, a bridge can observe Runners, and build up
56
- * state over the course of a test run.
57
- *
58
- * If you create a custom Runner, Printer and Bridge,
59
- * you can decide to manage notifications however you wish.
60
- *
61
- */
62
- private var _bridge:CallbackBridge;
63
-
64
- [Inject]
65
- public function set bridge(value:CallbackBridge):void
66
- {
67
- if (value !== _bridge)
68
- {
69
- _bridge = value;
70
- _bridge.addObserver(this);
71
- }
72
- }
73
-
74
- public function get bridge():CallbackBridge
75
- {
76
- return _bridge;
77
- }
78
-
79
54
  public function TextPrinter() {
80
55
  initialize();
81
56
  }
@@ -88,10 +63,6 @@ package asunit.printers {
88
63
  testTimes = [];
89
64
  warnings = [];
90
65
 
91
- footer = '';
92
- header = DEFAULT_HEADER;
93
- localPathPattern = LOCAL_PATH_PATTERN;
94
-
95
66
  if(stage) {
96
67
  initializeDisplay();
97
68
  } else {
@@ -117,7 +88,7 @@ package asunit.printers {
117
88
  private function getFailureStackTrace(failure:ITestFailure):String {
118
89
  var stack:String = "";
119
90
  stack = failure.thrownException.getStackTrace();
120
- //stack = stack.replace(localPathPattern, '');
91
+ if (hideLocalPaths) stack = stack.replace(localPathPattern, '');
121
92
  stack = stack.replace(/AssertionFailedError: /, '');
122
93
  stack += "\n\n";
123
94
  return stack;
@@ -218,7 +189,7 @@ package asunit.printers {
218
189
  println();
219
190
  println('Time Summary:');
220
191
  println();
221
- var len:Number = testTimes.length;
192
+ var len:Number = Math.min(performanceCount, testTimes.length);
222
193
  var total:Number = 0;
223
194
  var testTime:Object;
224
195
  for (var i:Number = 0; i < len; i++) {
@@ -310,7 +281,7 @@ package asunit.printers {
310
281
 
311
282
  var format:TextFormat = textDisplay.getTextFormat();
312
283
  format.font = '_sans';
313
- format.size = FONT_SIZE;
284
+ format.size = DEFAULT_FONT_SIZE;
314
285
  format.leftMargin = 5;
315
286
  format.rightMargin = 5;
316
287
  textDisplay.defaultTextFormat = format;
@@ -0,0 +1,127 @@
1
+
2
+ package asunit.printers {
3
+ import asunit.framework.ITestFailure;
4
+ import asunit.framework.ITestWarning;
5
+ import asunit.framework.IResult;
6
+ import asunit.framework.IRunListener;
7
+ import asunit.framework.ITestSuccess;
8
+ import asunit.framework.Method;
9
+
10
+ import flash.events.Event;
11
+ import flash.events.IOErrorEvent;
12
+ import flash.events.SecurityErrorEvent;
13
+ import flash.utils.getQualifiedClassName;
14
+
15
+ /**
16
+ * The <code>XMLPrinter</code> is used to transform AsUnit test results
17
+ * to JUnit-compatible XML content.
18
+ *
19
+ * This printer will send JUnit-compatible XML content to trace output. The XML content
20
+ * will be enclosed by '&lt;TestResults/&gt;' tags.
21
+ **/
22
+ public class XMLPrinter implements IRunListener {
23
+ public var traceResults:Boolean = true;
24
+
25
+ protected var projectName:String;
26
+ protected var contextName:String;
27
+ protected var messageQueue:Array;
28
+ protected var testPrefix:String = "<TestResults>";
29
+ protected var testSuffix:String = "</TestResults>";
30
+
31
+ public function XMLPrinter(projectName:String = '', contextName:String = '') {
32
+ this.projectName = projectName;
33
+ this.contextName = contextName;
34
+ messageQueue = [];
35
+ }
36
+
37
+ public function onRunStarted():void {
38
+ if (testPrefix) {
39
+ sendMessage(testPrefix);
40
+ }
41
+ sendMessage("<startTestRun totalTestCount='0' projectName='" + projectName
42
+ + "' contextName='" + contextName +"' />");
43
+ }
44
+
45
+ public function onRunCompleted(result:IResult):void {
46
+ sendMessage('<endOfTestRun />');
47
+
48
+ if (testSuffix) {
49
+ sendMessage("</TestResults>");
50
+ }
51
+
52
+ if (traceResults) {
53
+ trace(toString());
54
+ }
55
+ }
56
+
57
+ public function onTestStarted(test:Object):void {
58
+ }
59
+
60
+ public function onTestCompleted(test:Object):void {
61
+ }
62
+
63
+ // works for both errors and failures
64
+ public function onTestFailure(failure:ITestFailure):void {
65
+ sendMessage(getFailureMessage(failure));
66
+ }
67
+
68
+ public function onTestSuccess(success:ITestSuccess):void {
69
+ var xmlMessageSuccess:String = "<testCase name='" + success.method
70
+ + "' testSuite='" + getQualifiedClassName(success.test) + "' status='success'/>";
71
+ sendMessage(xmlMessageSuccess);
72
+ }
73
+
74
+ public function onTestIgnored(method:Method):void {
75
+ var xmlMessageIgnore:String = "<testCase name='" + method.name
76
+ + "' testSuite='" + getQualifiedClassName(method.scope) + "' status='ignore'/>";
77
+ sendMessage(xmlMessageIgnore);
78
+ }
79
+
80
+ public function onWarning(warning:ITestWarning):void {
81
+ var xmlMessage:String = "<testCase name='" + warning.method.name
82
+ + "' testSuite='" + getQualifiedClassName(warning.method.scope) + "' status='warning'/>";
83
+ sendMessage(xmlMessage);
84
+ }
85
+
86
+ public function toString():String {
87
+ return messageQueue.join("\n");
88
+ }
89
+
90
+ protected function sendMessage(message:String):void {
91
+ messageQueue.push(message);
92
+ }
93
+
94
+ protected function getFailureMessage(failure:ITestFailure):String {
95
+ var status:String = failure.isFailure ? 'failure' : 'error';
96
+ var xml:String =
97
+ "<testCase name='" + failure.failedMethod
98
+ + "' testSuite='" + getQualifiedClassName(failure.failedTest)
99
+ + "' status='" + status + "'>"
100
+ + "<failure type='" + getQualifiedClassName(failure.thrownException) + "' >"
101
+
102
+ + "<messageInfo>" + xmlEscapeMessage(failure.exceptionMessage)
103
+ + "</messageInfo>"
104
+
105
+ + "<stackTraceInfo>" + xmlEscapeMessage(failure.thrownException.getStackTrace())
106
+ + "</stackTraceInfo>"
107
+
108
+ + "</failure>"
109
+ + "</testCase>";
110
+
111
+ return xml;
112
+ }
113
+
114
+ protected static function xmlEscapeMessage(message:String):String {
115
+ if (!message) return '';
116
+
117
+ var escape:XML = <escape/>;
118
+ escape.setChildren( message );
119
+ return escape.children()[0].toXMLString();
120
+ }
121
+ }
122
+ }
123
+
124
+
125
+
126
+
127
+
@@ -1,11 +1,16 @@
1
1
  package asunit.runners {
2
2
 
3
+ import asunit.framework.IResult;
3
4
  import asunit.framework.LegacyTestIterator;
4
5
  import asunit.framework.TestIterator;
5
6
 
6
7
  public class LegacyRunner extends TestRunner {
7
8
 
8
- override protected function createTestIterator(test:*, testMethodName:String):TestIterator {
9
+ public function LegacyRunner(result:IResult = null) {
10
+ super(result);
11
+ }
12
+
13
+ override protected function createTestIterator(test:*, testMethodName:String):TestIterator {
9
14
  return new LegacyTestIterator(test, testMethodName);
10
15
  }
11
16
  }
@@ -1,41 +1,41 @@
1
1
  package asunit.runners {
2
-
3
- import asunit.framework.CallbackBridge;
4
- import asunit.framework.IResult;
5
- import asunit.framework.IRunner;
6
- import asunit.framework.IRunnerFactory;
7
- import asunit.framework.RunnerFactory;
8
- import asunit.util.Iterator;
9
- import asunit.framework.SuiteIterator;
10
-
11
- import flash.display.DisplayObjectContainer;
12
- import flash.events.Event;
13
- import flash.events.EventDispatcher;
14
- import flash.events.IEventDispatcher;
15
- import flash.events.TimerEvent;
16
- import flash.utils.Timer;
17
- import flash.utils.getDefinitionByName;
2
+
3
+ import asunit.framework.IResult;
4
+ import asunit.framework.IRunner;
5
+ import asunit.framework.IRunnerFactory;
6
+ import asunit.framework.Result;
7
+ import asunit.framework.RunnerFactory;
8
+ import asunit.framework.SuiteIterator;
9
+ import asunit.util.Iterator;
10
+ import org.swiftsuspenders.Injector;
18
11
 
19
- import p2.reflect.Reflection;
20
- import p2.reflect.ReflectionMetaData;
21
-
22
- public class SuiteRunner implements IEventDispatcher, IRunner {
12
+ import flash.display.DisplayObjectContainer;
13
+ import flash.events.Event;
14
+ import flash.events.EventDispatcher;
15
+ import flash.events.TimerEvent;
16
+ import flash.utils.Timer;
17
+
18
+ public class SuiteRunner extends EventDispatcher implements IRunner {
23
19
 
24
- [Inject]
25
- public var bridge:CallbackBridge;
20
+ public var result:IResult;
26
21
 
27
- protected var dispatcher:IEventDispatcher;
28
22
  protected var testClasses:Iterator;
29
23
  protected var timer:Timer;
30
24
  protected var visualContext:DisplayObjectContainer;
31
25
  protected var testMethod:String;
32
-
33
- private var _factory:IRunnerFactory;
26
+ protected var injector:Injector;
27
+ protected var factory:IRunnerFactory;
34
28
 
35
- public function SuiteRunner() {
36
- timer = new Timer(0, 1);
37
- dispatcher = new EventDispatcher();
38
- }
29
+ public function SuiteRunner(factory:IRunnerFactory = null, result:IResult = null, injector:Injector = null) {
30
+ timer = new Timer(0, 1);
31
+
32
+ this.injector = injector ||= new Injector();
33
+ injector.mapValue(Injector, injector);
34
+ this.result = result ||= new Result();
35
+ injector.mapValue(IResult, result);
36
+ this.factory = factory ||= injector.instantiate(RunnerFactory);
37
+ injector.mapValue(IRunnerFactory, factory);
38
+ }
39
39
 
40
40
  public function run(suite:Class, testMethod:String=null, visualContext:DisplayObjectContainer=null):void {
41
41
  this.visualContext = visualContext;
@@ -43,20 +43,8 @@ package asunit.runners {
43
43
  runSuite(suite);
44
44
  }
45
45
 
46
- public function shouldRunTest(testClass:Class):Boolean {
47
- return bridge.shouldRunTest(testClass);
48
- }
49
-
50
- public function set factory(factory:IRunnerFactory):void {
51
- _factory = factory;
52
- }
53
-
54
- public function get factory():IRunnerFactory {
55
- return _factory ||= new RunnerFactory();
56
- }
57
-
58
46
  protected function runSuite(suite:*):void {
59
- testClasses = new SuiteIterator(suite, bridge);
47
+ testClasses = new SuiteIterator(suite);
60
48
  timer.addEventListener(TimerEvent.TIMER, runNextTest);
61
49
 
62
50
  runNextTest();
@@ -97,29 +85,5 @@ package asunit.runners {
97
85
  */
98
86
  protected function onRunCompleted():void {
99
87
  }
100
-
101
- // BEGIN: Implement the IEvent Dispatcher Interface:
102
-
103
- public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void {
104
- dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
105
- }
106
-
107
- public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void {
108
- dispatcher.removeEventListener(type, listener, useCapture);
109
- }
110
-
111
- public function dispatchEvent(event:Event):Boolean {
112
- return dispatcher.dispatchEvent(event);
113
- }
114
-
115
- public function hasEventListener(type:String):Boolean {
116
- return dispatcher.hasEventListener(type);
117
- }
118
-
119
- public function willTrigger(type:String):Boolean {
120
- return dispatcher.willTrigger(type);
121
- }
122
-
123
- // END: Implement the IEvent Dispatcher Interface:
124
88
  }
125
89
  }
@@ -1,63 +1,52 @@
1
1
  package asunit.runners {
2
-
3
- import asunit.events.TimeoutCommandEvent;
4
- import asunit.framework.Assert;
5
- import asunit.framework.Async;
6
- import asunit.framework.CallbackBridge;
7
- import asunit.framework.IAsync;
8
- import asunit.framework.IResult;
9
- import asunit.framework.IRunner;
2
+
3
+ import asunit.events.TimeoutCommandEvent;
4
+ import asunit.framework.Assert;
5
+ import asunit.framework.Async;
6
+ import asunit.framework.IResult;
7
+ import asunit.framework.Result;
8
+ import asunit.framework.IAsync;
9
+ import asunit.framework.IRunner;
10
10
  import asunit.framework.IRunnerFactory;
11
- import asunit.framework.Method;
12
- import asunit.framework.TestFailure;
13
- import asunit.framework.TestIterator;
14
- import asunit.framework.TestSuccess;
15
- import asunit.framework.TestWarning;
16
- import asunit.util.ArrayIterator;
17
- import asunit.util.Iterator;
18
-
19
- import flash.display.DisplayObjectContainer;
20
- import flash.errors.IllegalOperationError;
21
- import flash.events.Event;
22
- import flash.events.EventDispatcher;
23
- import flash.events.IEventDispatcher;
24
- import flash.events.TimerEvent;
25
- import flash.utils.Timer;
26
- import flash.utils.clearTimeout;
27
- import flash.utils.getDefinitionByName;
28
- import flash.utils.getTimer;
29
- import flash.utils.setTimeout;
30
-
31
- import p2.reflect.Reflection;
32
- import p2.reflect.ReflectionMember;
33
- import p2.reflect.ReflectionMetaData;
34
- import p2.reflect.ReflectionVariable;
11
+ import asunit.framework.Method;
12
+ import asunit.framework.TestFailure;
13
+ import asunit.framework.TestIterator;
14
+ import asunit.framework.TestSuccess;
15
+ import asunit.framework.TestWarning;
16
+ import asunit.util.ArrayIterator;
17
+ import asunit.util.Iterator;
18
+ import flash.display.Sprite;
19
+ import org.swiftsuspenders.Injector;
20
+
21
+ import p2.reflect.Reflection;
22
+ import p2.reflect.ReflectionMetaData;
23
+ import p2.reflect.ReflectionVariable;
24
+
25
+ import flash.display.DisplayObjectContainer;
26
+ import flash.errors.IllegalOperationError;
27
+ import flash.events.Event;
28
+ import flash.events.EventDispatcher;
29
+ import flash.events.TimerEvent;
30
+ import flash.utils.Timer;
31
+ import flash.utils.getDefinitionByName;
32
+ import flash.utils.getTimer;
35
33
 
36
34
  public class TestRunner extends EventDispatcher implements IRunner {
37
- public static var ASYNC_NAME:String = 'asunit.framework::Async';
38
- public static var IASYNC_NAME:String = 'asunit.framework::IAsync';
39
- public static var DISPLAY_OBJECT_CONTAINER:String = 'flash.display::DisplayObjectContainer';
40
-
41
- /**
42
- * This is how the Runner connects to a printer.
43
- * The AsUnitCore will inject the requested bridge
44
- * based on the concrete data type.
45
- *
46
- * There should be a similar Injection point on
47
- * whatever printers are interested in what this
48
- * concrete runner will dispatch.
49
- */
50
- [Inject]
51
- public var bridge:CallbackBridge;
35
+
36
+ /**
37
+ *
38
+ */
39
+ //TODO: perhaps add a getter for this to IRunner
40
+ public var result:IResult;
52
41
 
53
42
  // partially exposed for unit testing
54
43
  internal var currentTest:Object;
55
44
  internal var async:IAsync;
45
+ /** Supplies dependencies to tests, e.g. IAsync, context Sprite. */
46
+ internal var testInjector:Injector;
56
47
 
57
- protected var asyncMembers:Iterator;
58
48
  protected var currentMethod:Method;
59
49
  protected var currentTestReflection:Reflection;
60
- protected var injectableMembers:Iterator;
61
50
  protected var methodIsExecuting:Boolean = false;
62
51
  protected var methodPassed:Boolean = true;
63
52
  protected var methodTimeoutID:Number;
@@ -68,100 +57,80 @@ package asunit.runners {
68
57
  protected var visualContext:DisplayObjectContainer;
69
58
  protected var visualInstances:Array;
70
59
 
71
- private var _factory:IRunnerFactory;
72
-
73
- public function TestRunner() {
60
+ public function TestRunner(result:IResult = null) {
74
61
  async = new Async();
75
- bridge = new CallbackBridge();
76
- timer = new Timer(0, 1);
77
- timer.addEventListener(TimerEvent.TIMER, runNextMethod);
62
+ this.result = result ||= new Result();
63
+ testInjector = new Injector();
64
+ testInjector.mapValue(IAsync, async);
65
+ testInjector.mapValue(Async, async);
66
+ timer = new Timer(0, 1);
67
+ timer.addEventListener(TimerEvent.TIMER, runNextMethods);
78
68
  visualInstances = [];
79
69
  }
80
70
 
81
- public function run(testOrSuite:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
82
- runMethodByName(testOrSuite, methodName, visualContext);
83
- }
84
-
85
- public function shouldRunTest(testClass:Class):Boolean {
86
- return bridge.shouldRunTest(testClass);
87
- }
88
-
89
- // This class doesn't really use the runner factory,
90
- // since it represents a leaf node in the test
91
- // hierarchy...
92
- public function set factory(factory:IRunnerFactory):void {
93
- _factory = factory;
71
+ public function runMethodByName(testOrSuite:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
72
+ run(testOrSuite, methodName, visualContext);
94
73
  }
95
74
 
96
- public function get factory():IRunnerFactory {
97
- return _factory;
98
- }
99
-
100
- public function runMethodByName(test:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
101
- currentTestReflection = Reflection.create(test);
75
+ public function run(test:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
76
+ currentTestReflection = Reflection.create(test);
102
77
  this.visualContext = visualContext;
78
+ testInjector.mapValue(Sprite, visualContext);
103
79
  currentMethod = null;
104
80
  testMethodNameReceived = (methodName != null);
105
81
 
106
82
  try {
107
- currentTest = new test();
83
+ currentTest = testInjector.instantiate(test);
108
84
  }
109
85
  catch(e:VerifyError) {
110
86
  warn("Unable to instantiate provided test case with: " + currentTestReflection.name);
111
87
  return;
112
88
  }
113
89
 
114
- initializeInjectableMembers();
115
-
116
90
  async.addEventListener(TimeoutCommandEvent.CALLED, onAsyncMethodCalled);
117
91
  async.addEventListener(TimeoutCommandEvent.TIMED_OUT, onAsyncMethodTimedOut);
118
92
 
119
93
  startTime = getTimer();
120
- bridge.onTestStarted(currentTest);
94
+ result.onTestStarted(currentTest);
121
95
 
122
96
  methodsToRun = createTestIterator(currentTest, methodName);
123
97
 
124
98
  if(methodsToRun.length == 0) {
125
99
  warn(">> We were unable to find any test methods in " + currentTestReflection.name + ". Did you set the --keep-as3-metadata flag?");
126
100
  }
127
- runNextMethod();
101
+
102
+ runNextMethods();
128
103
  }
129
104
 
130
105
  protected function createTestIterator(test:*, testMethodName:String):TestIterator {
131
106
  return new TestIterator(test, testMethodName);
132
107
  }
133
108
 
134
- protected function initializeInjectableMembers():void {
135
- injectableMembers = new ArrayIterator(currentTestReflection.getMembersByMetaData('Inject'));
136
- }
137
-
138
- protected function runNextMethod(e:TimerEvent = null):void {
139
- if(!testMethodNameReceived && methodsToRun.readyToTearDown) {
140
- removeInjectedMembers();
141
- removeInjectedVisualInstances();
142
- }
143
-
144
- if (testCompleted) {
145
- onTestCompleted();
146
- return;
147
- }
148
-
149
- if(methodsToRun.readyToSetUp) {
150
- prepareForSetUp();
151
- }
152
-
153
- runMethod(methodsToRun.next());
109
+ protected function runNextMethods(e:TimerEvent = null):void {
110
+ // Loop through as many as possible without hitting asynchronous tests.
111
+ // This keeps the call stack small.
112
+ while (methodsToRun.hasNext()) {
113
+ var hasAsyncPending:Boolean = runMethod(methodsToRun.next());
114
+ if (hasAsyncPending) return;
115
+ }
116
+
117
+ onTestCompleted();
154
118
  }
155
119
 
156
- protected function runMethod(method:Method):void {
157
- if (!method) return;
120
+ /**
121
+ *
122
+ * @param method
123
+ * @return true if asynchronous calls are pending after calling the test method.
124
+ */
125
+ protected function runMethod(method:Method):Boolean {
126
+ if (!method) return false;
158
127
  currentMethod = method;
159
128
  methodPassed = true; // innocent until proven guilty by recordFailure()
160
129
 
161
130
  if (currentMethod.ignore) {
162
- bridge.onTestIgnored(currentMethod);
131
+ result.onTestIgnored(currentMethod);
163
132
  onMethodCompleted();
164
- return;
133
+ return false;
165
134
  }
166
135
 
167
136
  // This is used to prevent async callbacks from triggering onMethodCompleted too early.
@@ -170,7 +139,13 @@ package asunit.runners {
170
139
  if (currentMethod.expects) {
171
140
  try {
172
141
  var errorClass:Class = getDefinitionByName(currentMethod.expects) as Class;
173
- Assert.assertThrows(errorClass, currentMethod.value);
142
+ var errorMessage:String = currentMethod.message;
143
+ if(errorMessage == null) {
144
+ Assert.assertThrows(errorClass, currentMethod.value);
145
+ }
146
+ else {
147
+ Assert.assertThrowsWithMessage(errorClass, errorMessage, currentMethod.value);
148
+ }
174
149
  }
175
150
  catch(definitionError:ReferenceError) {
176
151
  // NOTE: [luke] Added ReferenceError catch here b/c I had a bad class name in my expects.
@@ -192,22 +167,23 @@ package asunit.runners {
192
167
 
193
168
  methodIsExecuting = false;
194
169
 
195
- if (async.hasPending) return;
170
+ if (async.hasPending) return true;
196
171
 
197
172
  onMethodCompleted();
173
+ return false;
198
174
  }
199
175
 
200
- protected function onMethodCompleted():void {
176
+ protected function onMethodCompleted(wasAsync:Boolean = false):void {
201
177
  async.cancelPending();
202
178
 
203
179
  if (currentMethod.isTest && methodPassed && !currentMethod.ignore) {
204
- bridge.onTestSuccess(new TestSuccess(currentTest, currentMethod.name));
180
+ result.onTestSuccess(new TestSuccess(currentTest, currentMethod.name));
205
181
  }
206
182
 
207
- // Calling synchronously is faster but keeps adding to the call stack.
208
- runNextMethod();
183
+ if (wasAsync)
184
+ runNextMethods();
209
185
 
210
- // green thread for runNextMethod()
186
+ // green thread for runNextMethods()
211
187
  // This runs much slower in Flash Player 10.1.
212
188
  //timer.reset();
213
189
  //timer.start();
@@ -231,12 +207,12 @@ package asunit.runners {
231
207
 
232
208
  protected function recordFailure(error:Error):void {
233
209
  methodPassed = false;
234
- bridge.onTestFailure(new TestFailure(currentTest, currentMethod.name, error));
210
+ result.onTestFailure(new TestFailure(currentTest, currentMethod.name, error));
235
211
  }
236
212
 
237
213
  protected function onAsyncMethodCompleted(event:Event = null):void {
238
214
  if (!methodIsExecuting && !async.hasPending) {
239
- onMethodCompleted();
215
+ onMethodCompleted(true);
240
216
  }
241
217
  }
242
218
 
@@ -245,158 +221,17 @@ package asunit.runners {
245
221
  async.removeEventListener(TimeoutCommandEvent.TIMED_OUT, onAsyncMethodTimedOut);
246
222
  async.cancelPending();
247
223
 
248
- bridge.onTestCompleted(currentTest);
224
+ result.onTestCompleted(currentTest);
249
225
 
250
226
  dispatchEvent(new Event(Event.COMPLETE));
251
227
  }
252
228
 
253
229
  protected function get testCompleted():Boolean {
254
230
  return (!methodsToRun.hasNext() && !async.hasPending);
255
- }
256
-
257
- protected function removeInjectedMembers():void {
258
- var member:ReflectionVariable;
259
- while(injectableMembers.hasNext()) {
260
- removeInjectedMember(injectableMembers.next());
261
- }
262
- injectableMembers.reset();
263
- }
264
-
265
- protected function removeInjectedVisualInstances():void {
266
- var visuals:Iterator = new ArrayIterator(visualInstances);
267
- while(visuals.hasNext()) {
268
- visualContext.removeChild(visuals.next());
269
- }
270
- visualInstances = [];
271
- }
272
-
273
- protected function removeInjectedMember(member:ReflectionVariable):void {
274
- if(!member) return;
275
- currentTest[member.name] = null;
276
- }
277
-
278
- protected function prepareForSetUp():void {
279
- injectMembers();
280
- }
281
-
282
- protected function injectMembers():void {
283
- var member:ReflectionVariable;
284
- while(injectableMembers.hasNext()) {
285
- injectMember(injectableMembers.next());
286
- }
287
- injectableMembers.reset();
288
- }
289
231
 
290
- protected function injectMember(member:ReflectionVariable):void {
291
- if(!member) return;
292
- var definition:Class;
293
- try {
294
- definition = getDefinitionByName(member.type) as Class;
295
- }
296
- catch(referenceError:ReferenceError) {
297
- warn("Unable to [Inject] with " + member.type + ". Maybe this was an inner class? That makes it unavailable to external code, try putting it in it's own file.");
298
- return;
299
- }
300
- var reflection:Reflection = Reflection.create(definition);
301
- try {
302
- var instance:* = createInstanceFromReflection(reflection);
303
- configureInjectedInstance(member, instance);
304
- currentTest[member.name] = instance;
305
- }
306
- catch(e:VerifyError) {
307
- throw new VerifyError("Failed to instantiate " + member.type + " in order to inject public var " + member.name);
308
- }
309
- }
310
-
311
- protected function configureInjectedInstance(member:ReflectionVariable, instance:*):void {
312
- var injectTag:ReflectionMetaData = member.getMetaDataByName('Inject');
313
- var args:Array = injectTag.args;
314
- var arg:Object;
315
- var len:int = args.length;
316
- for(var i:int; i < len; i++) {
317
- arg = args[i];
318
- try {
319
- instance[arg.key] = coerceArgumentType(member, arg.value);
320
- }
321
- catch(e:ReferenceError) {
322
- var reflect:Reflection = Reflection.create(instance);
323
- warn("Unable to inject attribute " + arg.key + " on " + reflect.name);
324
- }
325
- }
326
- }
327
-
328
- protected function coerceArgumentType(member:ReflectionVariable, value:String):* {
329
- switch(value) {
330
- case "false" :
331
- return false;
332
- case "true" :
333
- return true;
334
- }
335
-
336
- return value;
337
232
  }
338
-
339
- protected function createInstanceFromReflection(reflection:Reflection):* {
340
- // Return the shared async instance if they're expecting the interface
341
- // or concrete instance, but NOT if their Inject is merely a subclass...
342
- if(reflection.name == ASYNC_NAME || reflection.name == IASYNC_NAME) {
343
- return async;
344
- }
345
-
346
- var clazz:Class = getClassReferenceFromReflection(reflection);
347
- var constructorReflection:Reflection = Reflection.create(clazz);
348
- try {
349
- var instance:* = new constructorReflection.classReference();
350
- }
351
- catch(e:VerifyError) {
352
- warn("Unable to instantiate: " + reflection.name + " for injection");
353
- }
354
-
355
- if(constructorReflection.isA(DISPLAY_OBJECT_CONTAINER)) {
356
- // Add injected DisplayObjectContainers to a collection
357
- // for removal, and add them to the visualContext if
358
- // one was provided to the run() method.
359
- if(visualContext) {
360
- visualInstances.push(instance);
361
- visualContext.addChild(instance);
362
- }
363
- else {
364
- warn("TestRunner is injecting a DisplayObjectContainer on your Test but wasn't given a visualContext when run was called. This means your visual entity will not be attached to the Display List.");
365
- }
366
- }
367
-
368
- return instance;
369
- }
370
-
371
233
  protected function warn(message:String, method:Method=null):void {
372
- bridge.onWarning(new TestWarning(message, method));
373
- }
374
-
375
- protected function getClassReferenceFromReflection(reflection:Reflection):Class {
376
- // This will attempt to deal with I-prefixed interfaces - like IAsync.
377
- if(reflection.isInterface) {
378
- return attemptToGetClassReferenceFromReflection(reflection);
379
- }
380
- return reflection.classReference;
381
- }
382
-
383
- protected function attemptToGetClassReferenceFromReflection(reflection:Reflection):Class {
384
- var fullName:String = reflection.name;
385
- var parts:Array = fullName.split("::");
386
- var interfaceName:String = parts.pop();
387
- var expr:RegExp = /I([AZ].+)/;
388
- var match:Object = expr.exec(interfaceName);
389
- if(match) {
390
- parts.push(match[1]);
391
- var implementationName:String = parts.join("::");
392
- return Class(getDefinitionByName(implementationName));
393
- }
394
- throw new VerifyError("Unable to find class instance for interface " + fullName);
395
- }
396
-
397
- // TODO: Implement this method:
398
- protected function argumentFreeConstructor(reflection:Reflection):Boolean {
399
- return true;
234
+ result.onWarning(new TestWarning(message, method));
400
235
  }
401
236
  }
402
237
  }