| OLD | NEW |
| 1 // Copyright (c) 2011, 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 * testcase.dart: this file is sourced by unittest.dart. It defines [TestCase] | 8 * Represents the state for an individual unit test. |
| 9 * and assumes unittest defines the type [TestFunction]. | 9 * |
| 10 * Create by calling [test] or [solo_test]. |
| 10 */ | 11 */ |
| 11 | |
| 12 /** Summarizes information about a single test case. */ | |
| 13 class TestCase { | 12 class TestCase { |
| 14 /** Identifier for this test. */ | 13 /** Identifier for this test. */ |
| 15 final int id; | 14 final int id; |
| 16 | 15 |
| 17 /** A description of what the test is specifying. */ | 16 /** A description of what the test is specifying. */ |
| 18 final String description; | 17 final String description; |
| 19 | 18 |
| 20 /** The setup function to call before the test, if any. */ | 19 /** The setup function to call before the test, if any. */ |
| 21 Function _setUp; | 20 Function setUp; |
| 22 | |
| 23 Function get setUp => _setUp; | |
| 24 set setUp(Function value) => _setUp = value; | |
| 25 | 21 |
| 26 /** The teardown function to call after the test, if any. */ | 22 /** The teardown function to call after the test, if any. */ |
| 27 Function _tearDown; | 23 Function tearDown; |
| 28 | |
| 29 Function get tearDown => _tearDown; | |
| 30 set tearDown(Function value) => _tearDown = value; | |
| 31 | 24 |
| 32 /** The body of the test case. */ | 25 /** The body of the test case. */ |
| 33 TestFunction test; | 26 TestFunction testFunction; |
| 34 | 27 |
| 35 /** | 28 /** |
| 36 * Remaining number of callbacks functions that must reach a 'done' state | 29 * Remaining number of callbacks functions that must reach a 'done' state |
| 37 * to wait for before the test completes. | 30 * to wait for before the test completes. |
| 38 */ | 31 */ |
| 39 int callbackFunctionsOutstanding; | 32 int _callbackFunctionsOutstanding = 0; |
| 40 | 33 |
| 34 String _message = ''; |
| 41 /** Error or failure message. */ | 35 /** Error or failure message. */ |
| 42 String message = ''; | 36 String get message => _message; |
| 43 | 37 |
| 38 String _result; |
| 44 /** | 39 /** |
| 45 * 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. |
| 46 */ | 41 */ |
| 47 String result; | 42 String get result => _result; |
| 48 | 43 |
| 49 /** Stack trace associated with this test, or null if it succeeded. */ | 44 String _stackTrace; |
| 50 String stackTrace; | 45 /** Stack trace associated with this test, or [null] if it succeeded. */ |
| 46 String get stackTrace => _stackTrace; |
| 51 | 47 |
| 52 /** The group (or groups) under which this test is running. */ | 48 /** The group (or groups) under which this test is running. */ |
| 53 final String currentGroup; | 49 final String currentGroup; |
| 54 | 50 |
| 55 DateTime startTime; | 51 DateTime _startTime; |
| 52 DateTime get startTime => _startTime; |
| 56 | 53 |
| 57 Duration runningTime; | 54 Duration _runningTime; |
| 55 Duration get runningTime => _runningTime; |
| 58 | 56 |
| 59 bool enabled = true; | 57 bool enabled = true; |
| 60 | 58 |
| 61 bool _doneTeardown = false; | 59 bool _doneTeardown = false; |
| 62 | 60 |
| 63 Completer _testComplete; | 61 Completer _testComplete; |
| 64 | 62 |
| 65 TestCase(this.id, this.description, this.test, | 63 TestCase._internal(this.id, this.description, this.testFunction) |
| 66 this.callbackFunctionsOutstanding) | |
| 67 : currentGroup = _currentGroup, | 64 : currentGroup = _currentGroup, |
| 68 _setUp = _testSetup, | 65 setUp = _testSetup, |
| 69 _tearDown = _testTeardown; | 66 tearDown = _testTeardown; |
| 70 | 67 |
| 71 bool get isComplete => !enabled || result != null; | 68 bool get isComplete => !enabled || result != null; |
| 72 | 69 |
| 73 void _prepTest() { | 70 void _prepTest() { |
| 74 _config.onTestStart(this); | 71 _config.onTestStart(this); |
| 75 startTime = new DateTime.now(); | 72 _startTime = new DateTime.now(); |
| 76 runningTime = null; | 73 _runningTime = null; |
| 77 } | 74 } |
| 78 | 75 |
| 79 Future _runTest() { | 76 Future _runTest() { |
| 80 _prepTest(); | 77 _prepTest(); |
| 81 // Increment/decrement callbackFunctionsOutstanding to prevent | 78 // Increment/decrement callbackFunctionsOutstanding to prevent |
| 82 // synchronous 'async' callbacks from causing the test to be | 79 // synchronous 'async' callbacks from causing the test to be |
| 83 // marked as complete before the body is completely executed. | 80 // marked as complete before the body is completely executed. |
| 84 ++callbackFunctionsOutstanding; | 81 ++_callbackFunctionsOutstanding; |
| 85 var f = test(); | 82 var f = testFunction(); |
| 86 --callbackFunctionsOutstanding; | 83 --_callbackFunctionsOutstanding; |
| 87 if (f is Future) { | 84 if (f is Future) { |
| 88 f.then((_) => _finishTest()) | 85 f.then((_) => _finishTest()) |
| 89 .catchError((e) => fail("${e.error}")); | 86 .catchError((e) => fail("${e.error}")); |
| 90 return f; | 87 return f; |
| 91 } else { | 88 } else { |
| 92 _finishTest(); | 89 _finishTest(); |
| 93 return null; | 90 return null; |
| 94 } | 91 } |
| 95 } | 92 } |
| 96 | 93 |
| 97 void _finishTest() { | 94 void _finishTest() { |
| 98 if (result == null && callbackFunctionsOutstanding == 0) { | 95 if (result == null && _callbackFunctionsOutstanding == 0) { |
| 99 pass(); | 96 pass(); |
| 100 } | 97 } |
| 101 } | 98 } |
| 102 | 99 |
| 103 /** | 100 /** |
| 104 * Perform any associated [setUp] function and run the test. Returns | 101 * Perform any associated [_setUp] function and run the test. Returns |
| 105 * 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 |
| 106 * to completion synchronously, or is disabled, we return null, to | 103 * to completion synchronously, or is disabled, null is returned, to |
| 107 * tell unittest to schedule the next test immediately. | 104 * tell unittest to schedule the next test immediately. |
| 108 */ | 105 */ |
| 109 Future run() { | 106 Future _run() { |
| 110 if (!enabled) return null; | 107 if (!enabled) return null; |
| 111 | 108 |
| 112 result = stackTrace = null; | 109 _result = _stackTrace = null; |
| 113 message = ''; | 110 _message = ''; |
| 114 _doneTeardown = false; | 111 _doneTeardown = false; |
| 115 var rtn = _setUp == null ? null : _setUp(); | 112 var rtn = setUp == null ? null : setUp(); |
| 116 if (rtn is Future) { | 113 if (rtn is Future) { |
| 117 rtn.then((_) => _runTest()) | 114 rtn.then((_) => _runTest()) |
| 118 .catchError((e) { | 115 .catchError((e) { |
| 119 _prepTest(); | 116 _prepTest(); |
| 120 // Calling error() will result in the tearDown being done. | 117 // Calling error() will result in the tearDown being done. |
| 121 // One could debate whether tearDown should be done after | 118 // One could debate whether tearDown should be done after |
| 122 // a failed setUp. There is no right answer, but doing it | 119 // a failed setUp. There is no right answer, but doing it |
| 123 // seems to be the more conservative approach, because | 120 // seems to be the more conservative approach, because |
| 124 // unittest will not stop at a test failure. | 121 // unittest will not stop at a test failure. |
| 125 error("$description: Test setup failed: ${e.error}"); | 122 error("$description: Test setup failed: ${e.error}"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 140 void _notifyComplete() { | 137 void _notifyComplete() { |
| 141 if (_testComplete != null) { | 138 if (_testComplete != null) { |
| 142 _testComplete.complete(this); | 139 _testComplete.complete(this); |
| 143 _testComplete = null; | 140 _testComplete = null; |
| 144 } | 141 } |
| 145 } | 142 } |
| 146 | 143 |
| 147 // Set the results, notify the config, and return true if this | 144 // Set the results, notify the config, and return true if this |
| 148 // is the first time the result is being set. | 145 // is the first time the result is being set. |
| 149 void _setResult(String testResult, String messageText, String stack) { | 146 void _setResult(String testResult, String messageText, String stack) { |
| 150 message = messageText; | 147 _message = messageText; |
| 151 stackTrace = stack; | 148 _stackTrace = stack; |
| 152 if (result == null) { | 149 if (result == null) { |
| 153 result = testResult; | 150 _result = testResult; |
| 154 _config.onTestResult(this); | 151 _config.onTestResult(this); |
| 155 } else { | 152 } else { |
| 156 result = testResult; | 153 _result = testResult; |
| 157 _config.onTestResultChanged(this); | 154 _config.onTestResultChanged(this); |
| 158 } | 155 } |
| 159 } | 156 } |
| 160 | 157 |
| 161 void _complete(String testResult, | 158 void _complete(String testResult, |
| 162 [String messageText = '', | 159 [String messageText = '', |
| 163 String stack = '']) { | 160 String stack = '']) { |
| 164 if (runningTime == null) { | 161 if (runningTime == null) { |
| 165 runningTime = new DateTime.now().difference(startTime); | 162 _runningTime = new DateTime.now().difference(startTime); |
| 166 } | 163 } |
| 167 _setResult(testResult, messageText, stack); | 164 _setResult(testResult, messageText, stack); |
| 168 if (!_doneTeardown) { | 165 if (!_doneTeardown) { |
| 169 _doneTeardown = true; | 166 _doneTeardown = true; |
| 170 if (_tearDown != null) { | 167 if (tearDown != null) { |
| 171 var rtn = _tearDown(); | 168 var rtn = tearDown(); |
| 172 if (rtn is Future) { | 169 if (rtn is Future) { |
| 173 rtn.then((_) { | 170 rtn.then((_) { |
| 174 _notifyComplete(); | 171 _notifyComplete(); |
| 175 }) | 172 }) |
| 176 .catchError((e) { | 173 .catchError((e) { |
| 177 // We don't call fail() as that will potentially result in | 174 // We don't call fail() as that will potentially result in |
| 178 // spurious messages like 'test failed more than once'. | 175 // spurious messages like 'test failed more than once'. |
| 179 _setResult(ERROR, "$description: Test teardown failed: ${e.error}", | 176 _setResult(ERROR, "$description: Test teardown failed: ${e.error}", |
| 180 e.stackTrace.toString()); | 177 e.stackTrace.toString()); |
| 181 _notifyComplete(); | 178 _notifyComplete(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 200 _complete(ERROR, newMessage, stack); | 197 _complete(ERROR, newMessage, stack); |
| 201 } else { | 198 } else { |
| 202 _complete(FAIL, messageText, stack); | 199 _complete(FAIL, messageText, stack); |
| 203 } | 200 } |
| 204 } | 201 } |
| 205 | 202 |
| 206 void error(String messageText, [String stack = '']) { | 203 void error(String messageText, [String stack = '']) { |
| 207 _complete(ERROR, messageText, stack); | 204 _complete(ERROR, messageText, stack); |
| 208 } | 205 } |
| 209 | 206 |
| 210 void markCallbackComplete() { | 207 void _markCallbackComplete() { |
| 211 if (--callbackFunctionsOutstanding == 0 && !isComplete) { | 208 if (--_callbackFunctionsOutstanding == 0 && !isComplete) { |
| 212 pass(); | 209 pass(); |
| 213 } | 210 } |
| 214 } | 211 } |
| 215 } | 212 } |
| OLD | NEW |