Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: pkg/unittest/lib/src/test_case.dart

Issue 12452004: pkg/unittest: locking down TestCase (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fixed up dartdoc on TestCase and updated copyright year Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/unittest/lib/unittest.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 final 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 final 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 final TestFunction _test;
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;
58 bool get enabled => _enabled;
60 59
61 bool _doneTeardown = false; 60 bool _doneTeardown = false;
62 61
63 Completer _testComplete; 62 Completer _testComplete;
64 63
65 TestCase(this.id, this.description, this.test, 64 TestCase._internal(this.id, this.description, this._test)
66 this.callbackFunctionsOutstanding)
67 : currentGroup = _currentGroup, 65 : currentGroup = _currentGroup,
68 _setUp = _testSetup, 66 _setUp = _testSetup,
69 _tearDown = _testTeardown; 67 _tearDown = _testTeardown;
70 68
71 bool get isComplete => !enabled || result != null; 69 bool get isComplete => !enabled || result != null;
72 70
73 void _prepTest() { 71 void _prepTest() {
74 _config.onTestStart(this); 72 _config.onTestStart(this);
75 startTime = new DateTime.now(); 73 _startTime = new DateTime.now();
76 runningTime = null; 74 _runningTime = null;
77 } 75 }
78 76
79 Future _runTest() { 77 Future _runTest() {
80 _prepTest(); 78 _prepTest();
81 // Increment/decrement callbackFunctionsOutstanding to prevent 79 // Increment/decrement callbackFunctionsOutstanding to prevent
82 // synchronous 'async' callbacks from causing the test to be 80 // synchronous 'async' callbacks from causing the test to be
83 // marked as complete before the body is completely executed. 81 // marked as complete before the body is completely executed.
84 ++callbackFunctionsOutstanding; 82 ++_callbackFunctionsOutstanding;
85 var f = test(); 83 var f = _test();
86 --callbackFunctionsOutstanding; 84 --_callbackFunctionsOutstanding;
87 if (f is Future) { 85 if (f is Future) {
88 f.then((_) => _finishTest()) 86 f.then((_) => _finishTest())
89 .catchError((e) => fail("${e.error}")); 87 .catchError((e) => fail("${e.error}"));
90 return f; 88 return f;
91 } else { 89 } else {
92 _finishTest(); 90 _finishTest();
93 return null; 91 return null;
94 } 92 }
95 } 93 }
96 94
97 void _finishTest() { 95 void _finishTest() {
98 if (result == null && callbackFunctionsOutstanding == 0) { 96 if (result == null && _callbackFunctionsOutstanding == 0) {
99 pass(); 97 _pass();
100 } 98 }
101 } 99 }
102 100
103 /** 101 /**
104 * Perform any associated [setUp] function and run the test. Returns 102 * 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 103 * 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 104 * to completion synchronously, or is disabled, null is returned, to
107 * tell unittest to schedule the next test immediately. 105 * tell unittest to schedule the next test immediately.
108 */ 106 */
109 Future run() { 107 Future _run() {
110 if (!enabled) return null; 108 if (!enabled) return null;
111 109
112 result = stackTrace = null; 110 _result = _stackTrace = null;
113 message = ''; 111 _message = '';
114 _doneTeardown = false; 112 _doneTeardown = false;
115 var rtn = _setUp == null ? null : _setUp(); 113 var rtn = _setUp == null ? null : _setUp();
116 if (rtn is Future) { 114 if (rtn is Future) {
117 rtn.then((_) => _runTest()) 115 rtn.then((_) => _runTest())
118 .catchError((e) { 116 .catchError((e) {
119 _prepTest(); 117 _prepTest();
120 // Calling error() will result in the tearDown being done. 118 // Calling error() will result in the tearDown being done.
121 // One could debate whether tearDown should be done after 119 // One could debate whether tearDown should be done after
122 // a failed setUp. There is no right answer, but doing it 120 // a failed setUp. There is no right answer, but doing it
123 // seems to be the more conservative approach, because 121 // seems to be the more conservative approach, because
124 // unittest will not stop at a test failure. 122 // unittest will not stop at a test failure.
125 error("$description: Test setup failed: ${e.error}"); 123 _error("$description: Test setup failed: ${e.error}");
126 }); 124 });
127 } else { 125 } else {
128 var f = _runTest(); 126 var f = _runTest();
129 if (f != null) { 127 if (f != null) {
130 return f; 128 return f;
131 } 129 }
132 } 130 }
133 if (result == null) { // Not complete. 131 if (result == null) { // Not complete.
134 _testComplete = new Completer(); 132 _testComplete = new Completer();
135 return _testComplete.future; 133 return _testComplete.future;
136 } 134 }
137 return null; 135 return null;
138 } 136 }
139 137
140 void _notifyComplete() { 138 void _notifyComplete() {
141 if (_testComplete != null) { 139 if (_testComplete != null) {
142 _testComplete.complete(this); 140 _testComplete.complete(this);
143 _testComplete = null; 141 _testComplete = null;
144 } 142 }
145 } 143 }
146 144
147 // Set the results, notify the config, and return true if this 145 // Set the results, notify the config, and return true if this
148 // is the first time the result is being set. 146 // is the first time the result is being set.
149 void _setResult(String testResult, String messageText, String stack) { 147 void _setResult(String testResult, String messageText, String stack) {
150 message = messageText; 148 _message = messageText;
151 stackTrace = stack; 149 _stackTrace = stack;
152 if (result == null) { 150 if (result == null) {
153 result = testResult; 151 _result = testResult;
154 _config.onTestResult(this); 152 _config.onTestResult(this);
155 } else { 153 } else {
156 result = testResult; 154 _result = testResult;
157 _config.onTestResultChanged(this); 155 _config.onTestResultChanged(this);
158 } 156 }
159 } 157 }
160 158
161 void _complete(String testResult, 159 void _complete(String testResult,
162 [String messageText = '', 160 [String messageText = '',
163 String stack = '']) { 161 String stack = '']) {
164 if (runningTime == null) { 162 if (runningTime == null) {
165 // TODO(gram): currently the duration measurement code is blocked 163 // TODO(gram): currently the duration measurement code is blocked
166 // by issue 4437. When that is fixed replace the line below with: 164 // by issue 4437. When that is fixed replace the line below with:
167 // runningTime = new DateTime.now().difference(startTime); 165 // runningTime =
168 runningTime = new Duration(milliseconds: 0); 166 _runningTime = new Duration(milliseconds: 0);
169 } 167 }
170 _setResult(testResult, messageText, stack); 168 _setResult(testResult, messageText, stack);
171 if (!_doneTeardown) { 169 if (!_doneTeardown) {
172 _doneTeardown = true; 170 _doneTeardown = true;
173 if (_tearDown != null) { 171 if (_tearDown != null) {
174 var rtn = _tearDown(); 172 var rtn = _tearDown();
175 if (rtn is Future) { 173 if (rtn is Future) {
176 rtn.then((_) { 174 rtn.then((_) {
177 _notifyComplete(); 175 _notifyComplete();
178 }) 176 })
179 .catchError((e) { 177 .catchError((e) {
180 // We don't call fail() as that will potentially result in 178 // We don't call fail() as that will potentially result in
181 // spurious messages like 'test failed more than once'. 179 // spurious messages like 'test failed more than once'.
182 _setResult(ERROR, "$description: Test teardown failed: ${e.error}", 180 _setResult(ERROR, "$description: Test teardown failed: ${e.error}",
183 e.stackTrace.toString()); 181 e.stackTrace.toString());
184 _notifyComplete(); 182 _notifyComplete();
185 }); 183 });
186 return; 184 return;
187 } 185 }
188 } 186 }
189 } 187 }
190 _notifyComplete(); 188 _notifyComplete();
191 } 189 }
192 190
193 void pass() { 191 void _pass() {
194 _complete(PASS); 192 _complete(PASS);
195 } 193 }
196 194
197 void fail(String messageText, [String stack = '']) { 195 void _fail(String messageText, [String stack = '']) {
198 if (result != null) { 196 if (result != null) {
gram 2013/03/05 18:07:41 I know that somewhere I have seen code like curren
199 String newMessage = (result == PASS) 197 String newMessage = (result == PASS)
200 ? 'Test failed after initially passing: $messageText' 198 ? 'Test failed after initially passing: $messageText'
201 : 'Test failed more than once: $messageText'; 199 : 'Test failed more than once: $messageText';
202 // TODO(gram): Should we combine the stack with the old one? 200 // TODO(gram): Should we combine the stack with the old one?
203 _complete(ERROR, newMessage, stack); 201 _complete(ERROR, newMessage, stack);
204 } else { 202 } else {
205 _complete(FAIL, messageText, stack); 203 _complete(FAIL, messageText, stack);
206 } 204 }
207 } 205 }
208 206
209 void error(String messageText, [String stack = '']) { 207 void _error(String messageText, [String stack = '']) {
210 _complete(ERROR, messageText, stack); 208 _complete(ERROR, messageText, stack);
211 } 209 }
212 210
213 void markCallbackComplete() { 211 void _markCallbackComplete() {
214 if (--callbackFunctionsOutstanding == 0 && !isComplete) { 212 if (--_callbackFunctionsOutstanding == 0 && !isComplete) {
215 pass(); 213 _pass();
216 } 214 }
217 } 215 }
218 } 216 }
OLDNEW
« no previous file with comments | « no previous file | pkg/unittest/lib/unittest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698