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

Side by Side Diff: lib/src/internal_test_case.dart

Issue 934413002: Replace the existing unittest APIs with the new runner infrastructure. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: Code review changes Created 5 years, 10 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
« no previous file with comments | « lib/src/group_context.dart ('k') | lib/src/prints_matcher.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
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.
4
5 library unittest.internal_test_case;
6
7 import 'dart:async';
8
9 import '../unittest.dart';
10 import 'test_environment.dart';
11 import 'utils.dart';
12
13 /// An implementation of [TestCase] that exposes internal properties for other
14 /// unittest use.
15 class InternalTestCase implements TestCase {
16 final int id;
17 final String description;
18
19 /// The setup function to call before the test, if any.
20 Function _setUp;
21
22 /// The teardown function to call after the test, if any.
23 Function _tearDown;
24
25 /// The body of the test case.
26 TestFunction _testFunction;
27
28 /// Remaining number of callback functions that must reach a 'done' state
29 /// before the test completes.
30 int callbackFunctionsOutstanding = 0;
31
32 /// The error or failure message for the tests.
33 ///
34 /// Initially an empty string.
35 String message = '';
36
37 /// The result of the test case.
38 ///
39 /// If the test case has is completed, this will be one of [PASS], [FAIL], or
40 /// [ERROR]. Otherwise, it will be `null`.
41 String result;
42
43 /// Returns whether this test case passed.
44 bool get passed => result == PASS;
45
46 /// The stack trace for the error that caused this test case to fail, or
47 /// `null` if it succeeded.
48 StackTrace stackTrace;
49
50 /// The name of the group within which this test is running.
51 final String currentGroup;
52
53 /// The time the test case started running.
54 ///
55 /// `null` if the test hasn't yet begun running.
56 DateTime get startTime => _startTime;
57 DateTime _startTime;
58
59 /// The amount of time the test case took.
60 ///
61 /// `null` if the test hasn't finished running.
62 Duration get runningTime => _runningTime;
63 Duration _runningTime;
64
65 /// Whether this test is enabled.
66 ///
67 /// Disabled tests won't be run.
68 bool enabled = true;
69
70 /// A completer that will complete when the test is finished.
71 ///
72 /// This is only non-`null` when outstanding callbacks exist.
73 Completer _testComplete;
74
75 /// Whether this test case has finished running.
76 bool get isComplete => !enabled || result != null;
77
78 InternalTestCase(this.id, this.description, this._testFunction)
79 : currentGroup = environment.currentContext.fullName,
80 _setUp = environment.currentContext.testSetUp,
81 _tearDown = environment.currentContext.testTearDown;
82
83 /// A function that returns another function to handle errors from [Future]s.
84 ///
85 /// [stage] is a string description of the stage of testing that failed.
86 Function _errorHandler(String stage) => (e, stack) {
87 if (stack == null && e is Error) {
88 stack = e.stackTrace;
89 }
90 if (result == null || result == PASS) {
91 if (e is TestFailure) {
92 fail("$e", stack);
93 } else {
94 error("$stage failed: Caught $e", stack);
95 }
96 }
97 };
98
99 /// Performs any associated [_setUp] function and runs the test.
100 ///
101 /// Returns a [Future] that can be used to schedule the next test. If the test
102 /// runs to completion synchronously, or is disabled, null is returned, to
103 /// tell unittest to schedule the next test immediately.
104 Future run() {
105 if (!enabled) return new Future.value();
106
107 result = stackTrace = null;
108 message = '';
109
110 // Avoid calling [new Future] to avoid issue 11911.
111 return new Future.value().then((_) {
112 if (_setUp != null) return _setUp();
113 }).catchError(_errorHandler('Setup')).then((_) {
114 // Skip the test if setup failed.
115 if (result != null) return new Future.value();
116 config.onTestStart(this);
117 _startTime = new DateTime.now();
118 _runningTime = null;
119 callbackFunctionsOutstanding++;
120 var testReturn = _testFunction();
121 // If _testFunction() returned a future, we want to wait for it like we
122 // would a callback, so if a failure occurs while waiting, we can abort.
123 if (testReturn is Future) {
124 callbackFunctionsOutstanding++;
125 testReturn
126 .catchError(_errorHandler('Test'))
127 .whenComplete(markCallbackComplete);
128 }
129 }).catchError(_errorHandler('Test')).then((_) {
130 markCallbackComplete();
131 if (result == null) {
132 // Outstanding callbacks exist; we need to return a Future.
133 _testComplete = new Completer();
134 return _testComplete.future.whenComplete(() {
135 if (_tearDown != null) {
136 return _tearDown();
137 }
138 }).catchError(_errorHandler('Teardown'));
139 } else if (_tearDown != null) {
140 return _tearDown();
141 }
142 }).catchError(_errorHandler('Teardown')).whenComplete(() {
143 _setUp = null;
144 _tearDown = null;
145 _testFunction = null;
146 });
147 }
148
149 /// Marks the test as having completed with [testResult], which should be one
150 /// of [PASS], [FAIL], or [ERROR].
151 void _complete(String testResult,
152 [String messageText = '', StackTrace stack]) {
153 if (runningTime == null) {
154 // The startTime can be `null` if an error happened during setup. In this
155 // case we simply report a running time of 0.
156 if (startTime != null) {
157 _runningTime = new DateTime.now().difference(startTime);
158 } else {
159 _runningTime = const Duration(seconds: 0);
160 }
161 }
162 _setResult(testResult, messageText, stack);
163 if (_testComplete != null) {
164 var t = _testComplete;
165 _testComplete = null;
166 t.complete(this);
167 }
168 }
169
170 // Sets [this]'s fields to reflect the test result, and notifies the current
171 // configuration that the test has completed.
172 //
173 // Returns true if this is the first time the result has been set.
174 void _setResult(String testResult, String messageText, StackTrace stack) {
175 message = messageText;
176 stackTrace = getTrace(stack, formatStacks, filterStacks);
177 if (stackTrace == null) stackTrace = stack;
178 if (result == null) {
179 result = testResult;
180 config.onTestResult(this);
181 } else {
182 result = testResult;
183 config.onTestResultChanged(this);
184 }
185 }
186
187 /// Marks the test as having passed.
188 void pass() {
189 _complete(PASS);
190 }
191
192 void registerException(error, [StackTrace stackTrace]) {
193 var message = error is TestFailure ? error.message : 'Caught $error';
194 if (result == null) {
195 fail(message, stackTrace);
196 } else {
197 this.error(message, stackTrace);
198 }
199 }
200
201 /// Marks the test as having failed.
202 void fail(String messageText, [StackTrace stack]) {
203 if (result != null) {
204 var newMessage = result == PASS
205 ? 'Test failed after initially passing: $messageText'
206 : 'Test failed more than once: $messageText';
207 // TODO(gram): Should we combine the stack with the old one?
208 _complete(ERROR, newMessage, stack);
209 } else {
210 _complete(FAIL, messageText, stack);
211 }
212 }
213
214 /// Marks the test as having had an unexpected error.
215 void error(String messageText, [StackTrace stack]) {
216 _complete(ERROR, messageText, stack);
217 }
218
219 /// Indicates that an asynchronous callback has completed, and marks the test
220 /// as passing if all outstanding callbacks are complete.
221 void markCallbackComplete() {
222 callbackFunctionsOutstanding--;
223 if (callbackFunctionsOutstanding == 0 && !isComplete) pass();
224 }
225
226 String toString() => result != null ? "$description: $result" : description;
227 }
OLDNEW
« no previous file with comments | « lib/src/group_context.dart ('k') | lib/src/prints_matcher.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698