mas01mj@732
|
1 package asunit.textui {
|
mas01mj@732
|
2 import asunit.errors.AssertionFailedError;
|
mas01mj@732
|
3 import asunit.framework.Test;
|
mas01mj@732
|
4 import asunit.framework.TestFailure;
|
mas01mj@732
|
5 import asunit.framework.TestListener;
|
mas01mj@732
|
6 import asunit.framework.TestResult;
|
mas01mj@732
|
7 import asunit.runner.BaseTestRunner;
|
mas01mj@732
|
8 import asunit.runner.Version;
|
mas01mj@732
|
9
|
mas01mj@732
|
10 import flash.display.Sprite;
|
mas01mj@732
|
11 import flash.events.*;
|
mas01mj@732
|
12 import flash.system.Capabilities;
|
mas01mj@732
|
13 import flash.text.TextField;
|
mas01mj@732
|
14 import flash.text.TextFormat;
|
mas01mj@732
|
15 import flash.utils.getTimer;
|
mas01mj@732
|
16 import flash.utils.setInterval;
|
mas01mj@732
|
17 import flash.utils.setTimeout;
|
mas01mj@732
|
18
|
mas01mj@732
|
19 /**
|
mas01mj@732
|
20 * This is the base class for collecting test output and formatting for different
|
mas01mj@732
|
21 * displays.
|
mas01mj@732
|
22 *
|
mas01mj@732
|
23 * This class simply presents test results as if they were being shown on a terminal.
|
mas01mj@732
|
24 *
|
mas01mj@732
|
25 * The <code>XMLResultPrinter</code> provides a good example of how this class can
|
mas01mj@732
|
26 * be subclassed and used to emit different/additional output.
|
mas01mj@732
|
27 *
|
mas01mj@732
|
28 * @see XMLResultPrinter
|
mas01mj@732
|
29 **/
|
mas01mj@732
|
30 public class ResultPrinter extends Sprite implements TestListener {
|
mas01mj@732
|
31 private var fColumn:int = 0;
|
mas01mj@732
|
32 private var textArea:TextField;
|
mas01mj@732
|
33 private var gutter:uint = 0;
|
mas01mj@732
|
34 private var backgroundColor:uint = 0x333333;
|
mas01mj@732
|
35 private var bar:SuccessBar;
|
mas01mj@732
|
36 private var barHeight:Number = 3;
|
mas01mj@732
|
37 private var showTrace:Boolean;
|
mas01mj@732
|
38 protected var startTime:Number;
|
mas01mj@732
|
39 protected var testTimes:Array;
|
mas01mj@732
|
40
|
mas01mj@732
|
41 public function ResultPrinter(showTrace:Boolean = false) {
|
mas01mj@732
|
42 this.showTrace = showTrace;
|
mas01mj@732
|
43 testTimes = new Array();
|
mas01mj@732
|
44 configureAssets();
|
mas01mj@732
|
45 println();
|
mas01mj@732
|
46
|
mas01mj@732
|
47 // Create a loop so that the FDBTask
|
mas01mj@732
|
48 // can halt execution properly:
|
mas01mj@732
|
49 setInterval(function():void {
|
mas01mj@732
|
50 }, 500);
|
mas01mj@732
|
51 }
|
mas01mj@732
|
52
|
mas01mj@732
|
53 private function configureAssets():void {
|
mas01mj@732
|
54 textArea = new TextField();
|
mas01mj@732
|
55 textArea.background = true;
|
mas01mj@732
|
56 textArea.backgroundColor = backgroundColor;
|
mas01mj@732
|
57 textArea.border = true;
|
mas01mj@732
|
58 textArea.wordWrap = true;
|
mas01mj@732
|
59 var format:TextFormat = new TextFormat();
|
mas01mj@732
|
60 format.font = "Verdana";
|
mas01mj@732
|
61 format.size = 10;
|
mas01mj@732
|
62 format.color = 0xFFFFFF;
|
mas01mj@732
|
63 textArea.defaultTextFormat = format;
|
mas01mj@732
|
64 addChild(textArea);
|
mas01mj@732
|
65 println("AsUnit " + Version.id() + " by Luke Bayes and Ali Mills");
|
mas01mj@732
|
66 println("");
|
mas01mj@732
|
67 println("Flash Player version: " + Capabilities.version);
|
mas01mj@732
|
68
|
mas01mj@732
|
69 bar = new SuccessBar();
|
mas01mj@732
|
70 addChild(bar);
|
mas01mj@732
|
71 }
|
mas01mj@732
|
72
|
mas01mj@732
|
73 public function setShowTrace(showTrace:Boolean):void {
|
mas01mj@732
|
74 this.showTrace = showTrace;
|
mas01mj@732
|
75 }
|
mas01mj@732
|
76
|
mas01mj@732
|
77 public override function set width(w:Number):void {
|
mas01mj@732
|
78 textArea.x = gutter;
|
mas01mj@732
|
79 textArea.width = w - gutter*2;
|
mas01mj@732
|
80 bar.x = gutter;
|
mas01mj@732
|
81 bar.width = textArea.width;
|
mas01mj@732
|
82 }
|
mas01mj@732
|
83
|
mas01mj@732
|
84 public override function set height(h:Number):void {
|
mas01mj@732
|
85 textArea.height = h - ((gutter*2) + barHeight);
|
mas01mj@732
|
86 textArea.y = gutter;
|
mas01mj@732
|
87 bar.y = h - (gutter + barHeight);
|
mas01mj@732
|
88 bar.height = barHeight;
|
mas01mj@732
|
89 }
|
mas01mj@732
|
90
|
mas01mj@732
|
91 public function println(...args:Array):void {
|
mas01mj@732
|
92 textArea.appendText(args.toString() + "\n");
|
mas01mj@732
|
93 }
|
mas01mj@732
|
94
|
mas01mj@732
|
95 public function print(...args:Array):void {
|
mas01mj@732
|
96 textArea.appendText(args.toString());
|
mas01mj@732
|
97 }
|
mas01mj@732
|
98
|
mas01mj@732
|
99 /**
|
mas01mj@732
|
100 * API for use by textui.TestRunner
|
mas01mj@732
|
101 */
|
mas01mj@732
|
102
|
mas01mj@732
|
103 public function run(test:Test):void {
|
mas01mj@732
|
104 }
|
mas01mj@732
|
105
|
mas01mj@732
|
106 public function printResult(result:TestResult, runTime:Number):void {
|
mas01mj@732
|
107 printHeader(runTime);
|
mas01mj@732
|
108 printErrors(result);
|
mas01mj@732
|
109 printFailures(result);
|
mas01mj@732
|
110 printFooter(result);
|
mas01mj@732
|
111
|
mas01mj@732
|
112 bar.setSuccess(result.wasSuccessful());
|
mas01mj@732
|
113 if(showTrace) {
|
mas01mj@732
|
114 trace(textArea.text.split("\r").join("\n"));
|
mas01mj@732
|
115 }
|
mas01mj@732
|
116 }
|
mas01mj@732
|
117
|
mas01mj@732
|
118 /* Internal methods
|
mas01mj@732
|
119 */
|
mas01mj@732
|
120 protected function printHeader(runTime:Number):void {
|
mas01mj@732
|
121 println();
|
mas01mj@732
|
122 println();
|
mas01mj@732
|
123 println("Time: " + elapsedTimeAsString(runTime));
|
mas01mj@732
|
124 }
|
mas01mj@732
|
125
|
mas01mj@732
|
126 protected function printErrors(result:TestResult):void {
|
mas01mj@732
|
127 printDefects(result.errors(), result.errorCount(), "error");
|
mas01mj@732
|
128 }
|
mas01mj@732
|
129
|
mas01mj@732
|
130 protected function printFailures(result:TestResult):void {
|
mas01mj@732
|
131 printDefects(result.failures(), result.failureCount(), "failure");
|
mas01mj@732
|
132 }
|
mas01mj@732
|
133
|
mas01mj@732
|
134 protected function printDefects(booBoos:Object, count:int, type:String):void {
|
mas01mj@732
|
135 if (count == 0) {
|
mas01mj@732
|
136 return;
|
mas01mj@732
|
137 }
|
mas01mj@732
|
138 if (count == 1) {
|
mas01mj@732
|
139 println("There was " + count + " " + type + ":");
|
mas01mj@732
|
140 }
|
mas01mj@732
|
141 else {
|
mas01mj@732
|
142 println("There were " + count + " " + type + "s:");
|
mas01mj@732
|
143 }
|
mas01mj@732
|
144 var i:uint;
|
mas01mj@732
|
145 for each (var item:TestFailure in booBoos) {
|
mas01mj@732
|
146 printDefect(TestFailure(item), i);
|
mas01mj@732
|
147 i++;
|
mas01mj@732
|
148 }
|
mas01mj@732
|
149 }
|
mas01mj@732
|
150
|
mas01mj@732
|
151 public function printDefect(booBoo:TestFailure, count:int ):void { // only public for testing purposes
|
mas01mj@732
|
152 printDefectHeader(booBoo, count);
|
mas01mj@732
|
153 printDefectTrace(booBoo);
|
mas01mj@732
|
154 }
|
mas01mj@732
|
155
|
mas01mj@732
|
156 protected function printDefectHeader(booBoo:TestFailure, count:int):void {
|
mas01mj@732
|
157 // I feel like making this a println, then adding a line giving the throwable a chance to print something
|
mas01mj@732
|
158 // before we get to the stack trace.
|
mas01mj@732
|
159 var startIndex:uint = textArea.text.length;
|
mas01mj@732
|
160 println(count + ") " + booBoo.failedFeature());
|
mas01mj@732
|
161 var endIndex:uint = textArea.text.length;
|
mas01mj@732
|
162
|
mas01mj@732
|
163 var format:TextFormat = textArea.getTextFormat();
|
mas01mj@732
|
164 format.bold = true;
|
mas01mj@732
|
165
|
mas01mj@732
|
166 // GROSS HACK because of bug in flash player - TextField isn't accepting formats...
|
mas01mj@732
|
167 setTimeout(onFormatTimeout, 1, format, startIndex, endIndex);
|
mas01mj@732
|
168 }
|
mas01mj@732
|
169
|
mas01mj@732
|
170 public function onFormatTimeout(format:TextFormat, startIndex:uint, endIndex:uint):void {
|
mas01mj@732
|
171 textArea.setTextFormat(format, startIndex, endIndex);
|
mas01mj@732
|
172 }
|
mas01mj@732
|
173
|
mas01mj@732
|
174 protected function printDefectTrace(booBoo:TestFailure):void {
|
mas01mj@732
|
175 println(BaseTestRunner.getFilteredTrace(booBoo.thrownException().getStackTrace()));
|
mas01mj@732
|
176 }
|
mas01mj@732
|
177
|
mas01mj@732
|
178 protected function printFooter(result:TestResult):void {
|
mas01mj@732
|
179 println();
|
mas01mj@732
|
180 if (result.wasSuccessful()) {
|
mas01mj@732
|
181 print("OK");
|
mas01mj@732
|
182 println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
|
mas01mj@732
|
183 } else {
|
mas01mj@732
|
184 println("FAILURES!!!");
|
mas01mj@732
|
185 println("Tests run: " + result.runCount()+
|
mas01mj@732
|
186 ", Failures: "+result.failureCount()+
|
mas01mj@732
|
187 ", Errors: "+result.errorCount());
|
mas01mj@732
|
188 }
|
mas01mj@732
|
189
|
mas01mj@732
|
190 printTimeSummary();
|
mas01mj@732
|
191 println();
|
mas01mj@732
|
192 }
|
mas01mj@732
|
193
|
mas01mj@732
|
194 protected function printTimeSummary():void {
|
mas01mj@732
|
195 testTimes.sortOn('duration', Array.NUMERIC | Array.DESCENDING);
|
mas01mj@732
|
196 println();
|
mas01mj@732
|
197 println();
|
mas01mj@732
|
198 println('Time Summary:');
|
mas01mj@732
|
199 println();
|
mas01mj@732
|
200 var len:Number = testTimes.length;
|
mas01mj@732
|
201 for(var i:Number = 0; i < len; i++) {
|
mas01mj@732
|
202 println(testTimes[i].toString());
|
mas01mj@732
|
203 }
|
mas01mj@732
|
204 }
|
mas01mj@732
|
205
|
mas01mj@732
|
206 /**
|
mas01mj@732
|
207 * Returns the formatted string of the elapsed time.
|
mas01mj@732
|
208 * Duplicated from BaseTestRunner. Fix it.
|
mas01mj@732
|
209 */
|
mas01mj@732
|
210 protected function elapsedTimeAsString(runTime:Number):String {
|
mas01mj@732
|
211 return Number(runTime/1000).toString();
|
mas01mj@732
|
212 }
|
mas01mj@732
|
213
|
mas01mj@732
|
214 /**
|
mas01mj@732
|
215 * @see asunit.framework.TestListener#addError(Test, Throwable)
|
mas01mj@732
|
216 */
|
mas01mj@732
|
217 public function addError(test:Test, t:Error):void {
|
mas01mj@732
|
218 print("E");
|
mas01mj@732
|
219 }
|
mas01mj@732
|
220
|
mas01mj@732
|
221 /**
|
mas01mj@732
|
222 * @see asunit.framework.TestListener#addFailure(Test, AssertionFailedError)
|
mas01mj@732
|
223 */
|
mas01mj@732
|
224 public function addFailure(test:Test, t:AssertionFailedError):void {
|
mas01mj@732
|
225 print("F");
|
mas01mj@732
|
226 }
|
mas01mj@732
|
227
|
mas01mj@732
|
228 /**
|
mas01mj@732
|
229 * @see asunit.framework.TestListener#endTestMethod(test, testMethod);
|
mas01mj@732
|
230 */
|
mas01mj@732
|
231 public function startTestMethod(test:Test, methodName:String):void {
|
mas01mj@732
|
232 }
|
mas01mj@732
|
233
|
mas01mj@732
|
234 /**
|
mas01mj@732
|
235 * @see asunit.framework.TestListener#endTestMethod(test, testMethod);
|
mas01mj@732
|
236 */
|
mas01mj@732
|
237 public function endTestMethod(test:Test, methodName:String):void {
|
mas01mj@732
|
238 }
|
mas01mj@732
|
239
|
mas01mj@732
|
240 /**
|
mas01mj@732
|
241 * @see asunit.framework.TestListener#startTest(Test)
|
mas01mj@732
|
242 */
|
mas01mj@732
|
243 public function startTest(test:Test):void {
|
mas01mj@732
|
244 startTime = getTimer();
|
mas01mj@732
|
245 var count:uint = test.countTestCases();
|
mas01mj@732
|
246 for(var i:uint; i < count; i++) {
|
mas01mj@732
|
247 print(".");
|
mas01mj@732
|
248 if (fColumn++ >= 80) {
|
mas01mj@732
|
249 println();
|
mas01mj@732
|
250 fColumn = 0;
|
mas01mj@732
|
251 }
|
mas01mj@732
|
252 }
|
mas01mj@732
|
253 }
|
mas01mj@732
|
254
|
mas01mj@732
|
255 /**
|
mas01mj@732
|
256 * @see asunit.framework.TestListener#endTest(Test)
|
mas01mj@732
|
257 */
|
mas01mj@732
|
258 public function endTest(test:Test):void {
|
mas01mj@732
|
259 var duration:Number = getTimer() - startTime;
|
mas01mj@732
|
260 testTimes.push(TestTime.create(test, duration));
|
mas01mj@732
|
261 }
|
mas01mj@732
|
262 }
|
mas01mj@732
|
263 }
|
mas01mj@732
|
264
|
mas01mj@732
|
265 import flash.display.Sprite;
|
mas01mj@732
|
266
|
mas01mj@732
|
267 class SuccessBar extends Sprite {
|
mas01mj@732
|
268 private var myWidth:uint;
|
mas01mj@732
|
269 private var myHeight:uint;
|
mas01mj@732
|
270 private var bgColor:uint;
|
mas01mj@732
|
271 private var passingColor:uint = 0x00FF00;
|
mas01mj@732
|
272 private var failingColor:uint = 0xFD0000;
|
mas01mj@732
|
273
|
mas01mj@732
|
274 public function SuccessBar() {
|
mas01mj@732
|
275 }
|
mas01mj@732
|
276
|
mas01mj@732
|
277 public function setSuccess(success:Boolean):void {
|
mas01mj@732
|
278 bgColor = (success) ? passingColor : failingColor;
|
mas01mj@732
|
279 draw();
|
mas01mj@732
|
280 }
|
mas01mj@732
|
281
|
mas01mj@732
|
282 public override function set width(num:Number):void {
|
mas01mj@732
|
283 myWidth = num;
|
mas01mj@732
|
284 draw();
|
mas01mj@732
|
285 }
|
mas01mj@732
|
286
|
mas01mj@732
|
287 public override function set height(num:Number):void {
|
mas01mj@732
|
288 myHeight = num;
|
mas01mj@732
|
289 draw();
|
mas01mj@732
|
290 }
|
mas01mj@732
|
291
|
mas01mj@732
|
292 private function draw():void {
|
mas01mj@732
|
293 graphics.clear();
|
mas01mj@732
|
294 graphics.beginFill(bgColor);
|
mas01mj@732
|
295 graphics.drawRect(0, 0, myWidth, myHeight);
|
mas01mj@732
|
296 graphics.endFill();
|
mas01mj@732
|
297 }
|
mas01mj@732
|
298 }
|