| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 * testcase.dart: this file is sourced by unittest.dart. It defines [TestCase] | 8 * testcase.dart: this file is sourced by unittest.dart. It defines [TestCase] |
| 9 * and assumes unittest defines the type [TestFunction]. | 9 * and assumes unittest defines the type [TestFunction]. |
| 10 */ | 10 */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 final String currentGroup; | 53 final String currentGroup; |
| 54 | 54 |
| 55 DateTime startTime; | 55 DateTime startTime; |
| 56 | 56 |
| 57 Duration runningTime; | 57 Duration runningTime; |
| 58 | 58 |
| 59 bool enabled = true; | 59 bool enabled = true; |
| 60 | 60 |
| 61 bool _doneTeardown = false; | 61 bool _doneTeardown = false; |
| 62 | 62 |
| 63 Completer _testComplete; |
| 64 |
| 63 TestCase(this.id, this.description, this.test, | 65 TestCase(this.id, this.description, this.test, |
| 64 this.callbackFunctionsOutstanding) | 66 this.callbackFunctionsOutstanding) |
| 65 : currentGroup = _currentGroup, | 67 : currentGroup = _currentGroup, |
| 66 _setUp = _testSetup, | 68 _setUp = _testSetup, |
| 67 _tearDown = _testTeardown; | 69 _tearDown = _testTeardown; |
| 68 | 70 |
| 69 bool get isComplete => !enabled || result != null; | 71 bool get isComplete => !enabled || result != null; |
| 70 | 72 |
| 71 void run() { | 73 void _prepTest() { |
| 72 if (enabled) { | 74 _config.onTestStart(this); |
| 73 result = stackTrace = null; | 75 startTime = new DateTime.now(); |
| 74 message = ''; | 76 runningTime = null; |
| 75 _doneTeardown = false; | 77 } |
| 76 if (_setUp != null) { | 78 |
| 77 _setUp(); | 79 void _runTest() { |
| 78 } | 80 _prepTest(); |
| 79 _config.onTestStart(this); | 81 test(); |
| 80 startTime = new DateTime.now(); | 82 if (result == null && callbackFunctionsOutstanding == 0) { |
| 81 runningTime = null; | 83 pass(); |
| 82 test(); | 84 } |
| 85 } |
| 86 |
| 87 /** |
| 88 * Perform any associated [setUp] function and run the test. Returns |
| 89 * a [Future] that can be used to schedule the next test. If the test runs |
| 90 * to completion synchronously, or is disabled, we return null, to |
| 91 * tell unittest to schedule the next test immediately. |
| 92 */ |
| 93 Future run() { |
| 94 if (!enabled) return null; |
| 95 |
| 96 result = stackTrace = null; |
| 97 message = ''; |
| 98 _doneTeardown = false; |
| 99 var rtn = _setUp == null ? null : _setUp(); |
| 100 if (rtn is Future) { |
| 101 rtn.then(expectAsync1((_) =>_runTest(), |
| 102 id: '[Async setUp completion handler]')) |
| 103 .catchError((e) { |
| 104 _prepTest(); |
| 105 // Calling error() will result in the tearDown being done. |
| 106 // One could debate whether tearDown should be done after |
| 107 // a failed setUp. There is no right answer, but doing it |
| 108 // seems to be the more conservative approach, because |
| 109 // unittest will not stop at a test failure. |
| 110 error("$description: Test setup failed: ${e.error}"); |
| 111 }); |
| 112 } else { |
| 113 _runTest(); |
| 114 } |
| 115 if (result == null) { // Not complete. |
| 116 _testComplete = new Completer(); |
| 117 return _testComplete.future; |
| 118 } |
| 119 return null; |
| 120 } |
| 121 |
| 122 void _notifyComplete() { |
| 123 if (_testComplete != null) { |
| 124 _testComplete.complete(this); |
| 125 _testComplete = null; |
| 83 } | 126 } |
| 84 } | 127 } |
| 85 | 128 |
| 86 void _complete() { | 129 void _complete() { |
| 87 if (runningTime == null) { | 130 if (runningTime == null) { |
| 88 // TODO(gram): currently the duration measurement code is blocked | 131 // TODO(gram): currently the duration measurement code is blocked |
| 89 // by issue 4437. When that is fixed replace the line below with: | 132 // by issue 4437. When that is fixed replace the line below with: |
| 90 // runningTime = new DateTime.now().difference(startTime); | 133 // runningTime = new DateTime.now().difference(startTime); |
| 91 runningTime = new Duration(milliseconds: 0); | 134 runningTime = new Duration(milliseconds: 0); |
| 92 } | 135 } |
| 93 if (!_doneTeardown) { | 136 if (!_doneTeardown) { |
| 137 _doneTeardown = true; |
| 94 if (_tearDown != null) { | 138 if (_tearDown != null) { |
| 95 _tearDown(); | 139 var rtn = _tearDown(); |
| 140 if (rtn is Future) { |
| 141 rtn.then((_) { |
| 142 if (result == null) { |
| 143 // The test passed. In some cases we will already |
| 144 // have set this result (e.g. if the test was async |
| 145 // and all callbacks completed). If not, we do it here. |
| 146 pass(); |
| 147 } else { |
| 148 // The test has already been marked as pass/fail. |
| 149 // Just report the updated result. |
| 150 _config.onTestResult(this); |
| 151 } |
| 152 _notifyComplete(); |
| 153 }) |
| 154 .catchError((e) { |
| 155 // We don't call fail() as that will potentially result in |
| 156 // spurious messages like 'test failed more than once'. |
| 157 result = ERROR; |
| 158 message = "$description: Test teardown failed: ${e.error}"; |
| 159 _config.onTestResult(this); |
| 160 _notifyComplete(); |
| 161 }); |
| 162 return; |
| 163 } |
| 96 } | 164 } |
| 97 _doneTeardown = true; | |
| 98 } | 165 } |
| 99 _config.onTestResult(this); | 166 _config.onTestResult(this); |
| 167 _notifyComplete(); |
| 100 } | 168 } |
| 101 | 169 |
| 102 void pass() { | 170 void pass() { |
| 103 result = PASS; | 171 result = PASS; |
| 104 _complete(); | 172 _complete(); |
| 105 } | 173 } |
| 106 | 174 |
| 107 void fail(String messageText, [String stack = '']) { | 175 void fail(String messageText, [String stack = '']) { |
| 108 if (result != null) { | 176 if (result != null) { |
| 109 if (result == PASS) { | 177 if (result == PASS) { |
| 110 error('Test failed after initially passing: $messageText', stack); | 178 error('Test failed after initially passing: $messageText', stack); |
| 111 } else if (result == FAIL) { | 179 } else if (result == FAIL) { |
| 112 error('Test failed more than once: $messageText', stack); | 180 error('Test failed more than once: $messageText', stack); |
| 113 } | 181 } |
| 114 } else { | 182 } else { |
| 115 result = FAIL; | 183 result = FAIL; |
| 116 message = messageText; | 184 message = messageText; |
| 117 stackTrace = stack; | 185 stackTrace = stack; |
| 118 _complete(); | 186 _complete(); |
| 119 } | 187 } |
| 120 } | 188 } |
| 121 | 189 |
| 122 void error(String messageText, [String stack = '']) { | 190 void error(String messageText, [String stack = '']) { |
| 123 result = ERROR; | 191 result = ERROR; |
| 124 message = messageText; | 192 message = messageText; |
| 125 stackTrace = stack; | 193 stackTrace = stack; |
| 126 _complete(); | 194 _complete(); |
| 127 } | 195 } |
| 128 } | 196 } |
| OLD | NEW |