OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of unittest; | 5 part of unittest; |
6 | 6 |
7 /** | 7 /** |
8 * Represents the state for an individual unit test. | 8 * Represents the state for an individual unit test. |
9 * | 9 * |
10 * Create by calling [test] or [solo_test]. | 10 * Create by calling [test] or [solo_test]. |
(...skipping 23 matching lines...) Expand all Loading... |
34 String _message = ''; | 34 String _message = ''; |
35 /** Error or failure message. */ | 35 /** Error or failure message. */ |
36 String get message => _message; | 36 String get message => _message; |
37 | 37 |
38 String _result; | 38 String _result; |
39 /** | 39 /** |
40 * One of [PASS], [FAIL], [ERROR], or [null] if the test hasn't run yet. | 40 * One of [PASS], [FAIL], [ERROR], or [null] if the test hasn't run yet. |
41 */ | 41 */ |
42 String get result => _result; | 42 String get result => _result; |
43 | 43 |
44 String _stackTrace; | 44 Trace _stackTrace; |
45 /** Stack trace associated with this test, or [null] if it succeeded. */ | 45 /** Stack trace associated with this test, or [null] if it succeeded. */ |
46 String get stackTrace => _stackTrace; | 46 Trace get stackTrace => _stackTrace; |
47 | 47 |
48 /** The group (or groups) under which this test is running. */ | 48 /** The group (or groups) under which this test is running. */ |
49 final String currentGroup; | 49 final String currentGroup; |
50 | 50 |
51 DateTime _startTime; | 51 DateTime _startTime; |
52 DateTime get startTime => _startTime; | 52 DateTime get startTime => _startTime; |
53 | 53 |
54 Duration _runningTime; | 54 Duration _runningTime; |
55 Duration get runningTime => _runningTime; | 55 Duration get runningTime => _runningTime; |
56 | 56 |
(...skipping 18 matching lines...) Expand all Loading... |
75 | 75 |
76 Future _runTest() { | 76 Future _runTest() { |
77 _prepTest(); | 77 _prepTest(); |
78 // Increment/decrement callbackFunctionsOutstanding to prevent | 78 // Increment/decrement callbackFunctionsOutstanding to prevent |
79 // synchronous 'async' callbacks from causing the test to be | 79 // synchronous 'async' callbacks from causing the test to be |
80 // marked as complete before the body is completely executed. | 80 // marked as complete before the body is completely executed. |
81 ++_callbackFunctionsOutstanding; | 81 ++_callbackFunctionsOutstanding; |
82 var f = testFunction(); | 82 var f = testFunction(); |
83 --_callbackFunctionsOutstanding; | 83 --_callbackFunctionsOutstanding; |
84 if (f is Future) { | 84 if (f is Future) { |
85 return f.then((_) => _finishTest()) | 85 return f.then((_) => _finishTest()).catchError((error) { |
86 .catchError((error) { | 86 _registerException(this, error, getAttachedStackTrace(error)); |
87 var stack = getAttachedStackTrace(error); | 87 }); |
88 _registerException(this, error, stack); | |
89 }); | |
90 } else { | 88 } else { |
91 _finishTest(); | 89 _finishTest(); |
92 return null; | 90 return null; |
93 } | 91 } |
94 } | 92 } |
95 | 93 |
96 void _finishTest() { | 94 void _finishTest() { |
97 if (result == null && _callbackFunctionsOutstanding == 0) { | 95 if (result == null && _callbackFunctionsOutstanding == 0) { |
98 pass(); | 96 pass(); |
99 } | 97 } |
100 } | 98 } |
101 | 99 |
102 /** | 100 /** |
103 * Perform any associated [_setUp] function and run the test. Returns | 101 * Perform any associated [_setUp] function and run the test. Returns |
104 * a [Future] that can be used to schedule the next test. If the test runs | 102 * a [Future] that can be used to schedule the next test. If the test runs |
105 * to completion synchronously, or is disabled, null is returned, to | 103 * to completion synchronously, or is disabled, null is returned, to |
106 * tell unittest to schedule the next test immediately. | 104 * tell unittest to schedule the next test immediately. |
107 */ | 105 */ |
108 Future _run() { | 106 Future _run() { |
109 if (!enabled) return null; | 107 if (!enabled) return null; |
110 | 108 |
111 _result = _stackTrace = null; | 109 _result = _stackTrace = null; |
112 _message = ''; | 110 _message = ''; |
113 _doneTeardown = false; | 111 _doneTeardown = false; |
114 var rtn = setUp == null ? null : setUp(); | 112 var rtn = setUp == null ? null : setUp(); |
115 if (rtn is Future) { | 113 if (rtn is Future) { |
116 rtn.then((_) => _runTest()) | 114 rtn.then((_) => _runTest()).catchError((e) { |
117 .catchError((e) { | 115 _prepTest(); |
118 _prepTest(); | 116 // Calling error() will result in the tearDown being done. |
119 // Calling error() will result in the tearDown being done. | 117 // One could debate whether tearDown should be done after |
120 // One could debate whether tearDown should be done after | 118 // a failed setUp. There is no right answer, but doing it |
121 // a failed setUp. There is no right answer, but doing it | 119 // seems to be the more conservative approach, because |
122 // seems to be the more conservative approach, because | 120 // unittest will not stop at a test failure. |
123 // unittest will not stop at a test failure. | 121 error( |
124 var stack = getAttachedStackTrace(e); | 122 "$description: Test setup failed: $e", |
125 if (stack == null) stack = ''; | 123 getAttachedStackTrace(e)); |
126 error("$description: Test setup failed: $e", "$stack"); | 124 }); |
127 }); | |
128 } else { | 125 } else { |
129 var f = _runTest(); | 126 var f = _runTest(); |
130 if (f != null) { | 127 if (f != null) { |
131 return f; | 128 return f; |
132 } | 129 } |
133 } | 130 } |
134 if (result == null) { // Not complete. | 131 if (result == null) { // Not complete. |
135 _testComplete = new Completer(); | 132 _testComplete = new Completer(); |
136 return _testComplete.future; | 133 return _testComplete.future; |
137 } | 134 } |
138 return null; | 135 return null; |
139 } | 136 } |
140 | 137 |
141 void _notifyComplete() { | 138 void _notifyComplete() { |
142 if (_testComplete != null) { | 139 if (_testComplete != null) { |
143 _testComplete.complete(this); | 140 _testComplete.complete(this); |
144 _testComplete = null; | 141 _testComplete = null; |
145 } | 142 } |
146 } | 143 } |
147 | 144 |
148 // Set the results, notify the config, and return true if this | 145 // Set the results, notify the config, and return true if this |
149 // is the first time the result is being set. | 146 // is the first time the result is being set. |
150 void _setResult(String testResult, String messageText, String stack) { | 147 void _setResult(String testResult, String messageText, stack) { |
151 _message = messageText; | 148 _message = messageText; |
152 _stackTrace = _formatStack(stack); | 149 _stackTrace = _getTrace(stack); |
153 if (result == null) { | 150 if (result == null) { |
154 _result = testResult; | 151 _result = testResult; |
155 _config.onTestResult(this); | 152 _config.onTestResult(this); |
156 } else { | 153 } else { |
157 _result = testResult; | 154 _result = testResult; |
158 _config.onTestResultChanged(this); | 155 _config.onTestResultChanged(this); |
159 } | 156 } |
160 } | 157 } |
161 | 158 |
162 void _complete(String testResult, | 159 void _complete(String testResult, [String messageText = '', stack]) { |
163 [String messageText = '', | |
164 String stack = '']) { | |
165 if (runningTime == null) { | 160 if (runningTime == null) { |
166 // The startTime can be `null` if an error happened during setup. In this | 161 // The startTime can be `null` if an error happened during setup. In this |
167 // case we simply report a running time of 0. | 162 // case we simply report a running time of 0. |
168 if (startTime != null) { | 163 if (startTime != null) { |
169 _runningTime = new DateTime.now().difference(startTime); | 164 _runningTime = new DateTime.now().difference(startTime); |
170 } else { | 165 } else { |
171 _runningTime = const Duration(seconds: 0); | 166 _runningTime = const Duration(seconds: 0); |
172 } | 167 } |
173 } | 168 } |
174 _setResult(testResult, messageText, stack); | 169 _setResult(testResult, messageText, stack); |
(...skipping 17 matching lines...) Expand all Loading... |
192 } | 187 } |
193 } | 188 } |
194 } | 189 } |
195 _notifyComplete(); | 190 _notifyComplete(); |
196 } | 191 } |
197 | 192 |
198 void pass() { | 193 void pass() { |
199 _complete(PASS); | 194 _complete(PASS); |
200 } | 195 } |
201 | 196 |
202 void fail(String messageText, [String stack = '']) { | 197 void fail(String messageText, [stack]) { |
203 assert(stack != null); | |
204 if (result != null) { | 198 if (result != null) { |
205 String newMessage = (result == PASS) | 199 String newMessage = (result == PASS) |
206 ? 'Test failed after initially passing: $messageText' | 200 ? 'Test failed after initially passing: $messageText' |
207 : 'Test failed more than once: $messageText'; | 201 : 'Test failed more than once: $messageText'; |
208 // TODO(gram): Should we combine the stack with the old one? | 202 // TODO(gram): Should we combine the stack with the old one? |
209 _complete(ERROR, newMessage, stack); | 203 _complete(ERROR, newMessage, stack); |
210 } else { | 204 } else { |
211 _complete(FAIL, messageText, stack); | 205 _complete(FAIL, messageText, stack); |
212 } | 206 } |
213 } | 207 } |
214 | 208 |
215 void error(String messageText, [String stack = '']) { | 209 void error(String messageText, [stack]) { |
216 assert(stack != null); | |
217 _complete(ERROR, messageText, stack); | 210 _complete(ERROR, messageText, stack); |
218 } | 211 } |
219 | 212 |
220 void _markCallbackComplete() { | 213 void _markCallbackComplete() { |
221 if (--_callbackFunctionsOutstanding == 0 && !isComplete) { | 214 if (--_callbackFunctionsOutstanding == 0 && !isComplete) { |
222 pass(); | 215 pass(); |
223 } | 216 } |
224 } | 217 } |
225 } | 218 } |
OLD | NEW |