Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /** Whether to include elapsed time. */ | |
|
Siggi Cherem (dart-lang)
2012/09/20 17:37:27
+ copyright, + library, + general doc for the libr
| |
| 2 bool includeTime; | |
| 3 | |
| 4 /** Whether to regenerate layout test files. */ | |
| 5 bool regenerate; | |
| 6 | |
| 7 /** Whether to output test summary. */ | |
| 8 bool summarize; | |
| 9 | |
| 10 /** Whether to print results immediately as they come in. */ | |
| 11 bool immediate; | |
| 12 | |
| 13 /** Format strings to use for test result messages. */ | |
| 14 String listFormat, passFormat, failFormat, errorFormat; | |
| 15 | |
| 16 /** Path of the running test file. */ | |
| 17 String testfile; | |
| 18 | |
| 19 /** The filters must be set by the caller. */ | |
| 20 List includeFilters; | |
| 21 List excludeFilters; | |
| 22 | |
| 23 /** The print function to use. */ | |
| 24 Function tprint; | |
| 25 | |
| 26 /** A callback function to notify the caller we are done. */ | |
| 27 Function notifyDone; | |
| 28 | |
| 29 /** The action function to use. */ | |
| 30 Function action; | |
| 31 | |
| 32 class Macros { | |
| 33 static const String testTime = '<TIME>'; | |
| 34 static const String testfile = '<FILENAME>'; | |
| 35 static const String testGroup = '<GROUPNAME>'; | |
| 36 static const String testDescription = '<TESTNAME>'; | |
| 37 static const String testMessage = '<MESSAGE>'; | |
| 38 static const String testStacktrace = '<STACK>'; | |
| 39 } | |
| 40 | |
| 41 class TestRunnerConfiguration extends unittest.Configuration { | |
| 42 get name => 'Minimal test runner configuration'; | |
| 43 get autoStart => false; | |
| 44 | |
| 45 String formatMessage(filename, groupname, | |
| 46 [ testname = '', testTime = '', result = '', | |
| 47 message = '', stack = '' ]) { | |
| 48 var format = errorFormat; | |
| 49 if (result == 'pass') format = passFormat; | |
| 50 else if (result == 'fail') format = failFormat; | |
| 51 return format. | |
| 52 replaceAll(Macros.testTime, testTime). | |
| 53 replaceAll(Macros.testfile, filename). | |
| 54 replaceAll(Macros.testGroup, groupname). | |
| 55 replaceAll(Macros.testDescription, testname). | |
| 56 replaceAll(Macros.testMessage, message). | |
| 57 replaceAll(Macros.testStacktrace, stack); | |
| 58 } | |
| 59 | |
| 60 String elapsed(unittest.TestCase t) { | |
| 61 if (includeTime) { | |
| 62 double duration = t.runningTime.inMilliseconds.toDouble(); | |
| 63 duration /= 1000; | |
| 64 return '${duration.toStringAsFixed(3)}s '; | |
| 65 } else { | |
| 66 return ''; | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 void dumpTestResult(source, unittest.TestCase t) { | |
| 71 var groupName = '', testName = ''; | |
| 72 var idx = t.description.lastIndexOf('###'); | |
| 73 if (idx >= 0) { | |
| 74 groupName = t.description.substring(0, idx).replaceAll('###', ' '); | |
| 75 testName = t.description.substring(idx+3); | |
| 76 } else { | |
| 77 testName = t.description; | |
| 78 } | |
| 79 var stack = (t.stackTrace == null) ? '' : '${t.stackTrace} '; | |
| 80 var message = (t.message.length > 0) ? '${t.message} ' : ''; | |
| 81 var duration = elapsed(t); | |
| 82 tprint(formatMessage(source, '$groupName ', '$testName ', | |
| 83 duration, t.result, message, stack)); | |
| 84 } | |
| 85 | |
| 86 void onTestResult(unittest.TestCase testCase) { | |
| 87 if (immediate) { | |
| 88 dumpTestResult('$testfile ', testCase); | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 void printSummary(int passed, int failed, int errors, | |
| 93 [String uncaughtError = '']) { | |
| 94 tprint(''); | |
| 95 if (passed == 0 && failed == 0 && errors == 0) { | |
| 96 tprint('$testfile: No tests found.'); | |
| 97 } else if (failed == 0 && errors == 0 && uncaughtError == null) { | |
| 98 tprint('$testfile: All $passed tests passed.'); | |
| 99 } else { | |
| 100 if (uncaughtError != null) { | |
| 101 tprint('$testfile: Top-level uncaught error: $uncaughtError'); | |
| 102 } | |
| 103 tprint('$testfile: $passed PASSED, $failed FAILED, $errors ERRORS'); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 void onDone(int passed, int failed, int errors, | |
| 108 List<unittest.TestCase> results, | |
| 109 String uncaughtError) { | |
| 110 var success = (passed > 0 && failed == 0 && errors == 0 && | |
| 111 uncaughtError == null); | |
| 112 if (!immediate) { | |
| 113 for (final testCase in results) { | |
| 114 dumpTestResult('$testfile ', testCase); | |
| 115 } | |
| 116 } | |
| 117 if (summarize) { | |
| 118 printSummary(passed, failed, errors, uncaughtError); | |
| 119 } | |
| 120 if (notifyDone != null) { | |
| 121 notifyDone(success ? 0 : -1); | |
| 122 } | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 // Support for listing tests and groups. We use a minimal config. | |
| 127 class MinimalTestRunnerConfiguration extends unittest.Configuration { | |
| 128 get name => 'Minimal test runner configuration'; | |
| 129 get autoStart => false; | |
| 130 } | |
| 131 | |
| 132 String formatListMessage(filename, groupname, [ testname = '']) { | |
| 133 return listFormat. | |
| 134 replaceAll(Macros.testfile, filename). | |
| 135 replaceAll(Macros.testGroup, groupname). | |
| 136 replaceAll(Macros.testDescription, testname); | |
| 137 } | |
| 138 | |
| 139 listGroups() { | |
| 140 List tests = unittest.testCases; | |
| 141 Map groups = {}; | |
| 142 for (var t in tests) { | |
| 143 var groupName, testName = ''; | |
| 144 var idx = t.description.lastIndexOf('###'); | |
| 145 if (idx >= 0) { | |
| 146 groupName = t.description.substring(0, idx).replaceAll('###', ' '); | |
| 147 if (!groups.containsKey(groupName)) { | |
| 148 groups[groupName] = ''; | |
| 149 } | |
| 150 } | |
| 151 } | |
| 152 for (var g in groups.getKeys()) { | |
| 153 var msg = formatListMessage('$testfile ', '$g '); | |
| 154 print('###$msg'); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 listTests() { | |
| 159 List tests = unittest.testCases; | |
| 160 for (var t in tests) { | |
| 161 var groupName, testName = ''; | |
| 162 var idx = t.description.lastIndexOf('###'); | |
| 163 if (idx >= 0) { | |
| 164 groupName = t.description.substring(0, idx).replaceAll('###', ' '); | |
| 165 testName = t.description.substring(idx+3); | |
| 166 } else { | |
| 167 groupName = ''; | |
| 168 testName = t.description; | |
| 169 } | |
| 170 var msg = formatListMessage('$testfile ', '$groupName ', '$testName '); | |
| 171 print('###$msg'); | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 // Support for running in isolates. | |
| 176 | |
| 177 class TestRunnerChildConfiguration extends unittest.Configuration { | |
| 178 get name => 'Test runner child configuration'; | |
| 179 get autoStart => false; | |
| 180 | |
| 181 void onDone(int passed, int failed, int errors, | |
| 182 List<unittest.TestCase> results, String uncaughtError) { | |
| 183 unittest.TestCase test = results[0]; | |
| 184 parentPort.send([test.result, test.runningTime.inMilliseconds, | |
| 185 test.message, test.stackTrace]); | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 var parentPort; | |
| 190 var childTestMain; | |
| 191 runChildTest() { | |
| 192 port.receive((testName, sendport) { | |
| 193 parentPort = sendport; | |
| 194 unittest.configure(new TestRunnerChildConfiguration()); | |
| 195 unittest.groupSep = '###'; | |
| 196 unittest.group('', childTestMain); | |
| 197 unittest.filterTests(testName); | |
| 198 unittest.runTests(); | |
| 199 }); | |
| 200 } | |
| 201 | |
| 202 var testNum; | |
| 203 var failed; | |
| 204 var errors; | |
| 205 var passed; | |
| 206 | |
| 207 runParentTest() { | |
| 208 var tests = unittest.testCases; | |
| 209 tests[testNum].startTime = new Date.now(); | |
| 210 SendPort childPort = spawnFunction(runChildTest); | |
| 211 childPort.call(tests[testNum].description).then((results) { | |
| 212 var result = results[0]; | |
| 213 var duration = new Duration(milliseconds: results[1]); | |
| 214 var message = results[2]; | |
| 215 var stack = results[3]; | |
| 216 if (result == 'pass') { | |
| 217 tests[testNum].pass(); | |
| 218 ++passed; | |
| 219 } else if (result == 'fail') { | |
| 220 tests[testNum].fail(message, stack); | |
| 221 ++failed; | |
| 222 } else { | |
| 223 tests[testNum].error(message, stack); | |
| 224 ++errors; | |
| 225 } | |
| 226 tests[testNum].runningTime = duration; | |
| 227 ++testNum; | |
| 228 if (testNum < tests.length) { | |
| 229 runParentTest(); | |
| 230 } else { | |
| 231 unittest.config.onDone(passed, failed, errors, | |
| 232 unittest.testCases, null); | |
| 233 } | |
| 234 }); | |
| 235 } | |
| 236 | |
| 237 runIsolateTests() { | |
| 238 testNum = 0; | |
| 239 passed = failed = errors = 0; | |
| 240 runParentTest(); | |
| 241 } | |
| 242 | |
| 243 // Main | |
|
Siggi Cherem (dart-lang)
2012/09/20 17:37:27
?
gram
2012/09/20 18:58:03
Done.
| |
| 244 | |
| 245 filterTest(t) { | |
| 246 var name = t.description.replaceAll("###", " "); | |
| 247 if (includeFilters.length > 0) { | |
| 248 for (var f in includeFilters) { | |
| 249 if (name.indexOf(f) >= 0) return true; | |
| 250 } | |
| 251 return false; | |
| 252 } else if (excludeFilters.length > 0) { | |
| 253 for (var f in excludeFilters) { | |
| 254 if (name.indexOf(f) >= 0) return false; | |
| 255 } | |
| 256 return true; | |
| 257 } else { | |
| 258 return true; | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 runTests(testMain) { | |
| 263 childTestMain = testMain; | |
| 264 unittest.groupSep = '###'; | |
| 265 unittest.configure(new TestRunnerConfiguration()); | |
| 266 unittest.group('', testMain); | |
| 267 // Do any user-specified test filtering. | |
| 268 unittest.filterTests(filterTest); | |
| 269 if (action == null) { | |
| 270 unittest.runTests(); | |
| 271 } else { | |
| 272 action(); | |
| 273 } | |
| 274 } | |
| 275 | |
|
Siggi Cherem (dart-lang)
2012/09/20 17:37:27
remove line
| |
| OLD | NEW |