| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 library unittestTests; | |
| 6 import 'package:unittest/unittest.dart'; | |
| 7 import 'dart:async'; | 5 import 'dart:async'; |
| 8 import 'dart:collection'; | 6 import 'dart:collection'; |
| 9 part 'test_utils.dart'; | |
| 10 | 7 |
| 11 doesNotThrow() {} | 8 import 'package:unittest/unittest.dart'; |
| 12 doesThrow() { throw 'X'; } | |
| 13 | 9 |
| 14 class PrefixMatcher extends BaseMatcher { | 10 import 'test_common.dart'; |
| 15 final String _prefix; | 11 import 'test_utils.dart'; |
| 16 const PrefixMatcher(this._prefix); | |
| 17 bool matches(item, MatchState matchState) { | |
| 18 return item is String && | |
| 19 (collapseWhitespace(item)).startsWith(collapseWhitespace(_prefix)); | |
| 20 } | |
| 21 | |
| 22 Description describe(Description description) => | |
| 23 description.add('a string starting with '). | |
| 24 addDescriptionOf(collapseWhitespace(_prefix)). | |
| 25 add(' ignoring whitespace'); | |
| 26 } | |
| 27 | |
| 28 class Widget { | |
| 29 int price; | |
| 30 } | |
| 31 | |
| 32 class HasPrice extends CustomMatcher { | |
| 33 HasPrice(matcher) : | |
| 34 super("Widget with a price that is", "price", matcher); | |
| 35 featureValueOf(actual) => actual.price; | |
| 36 } | |
| 37 | |
| 38 class SimpleIterable extends IterableBase { | |
| 39 int count; | |
| 40 SimpleIterable(this.count); | |
| 41 | |
| 42 bool contains(int val) => count < val ? false : true; | |
| 43 | |
| 44 bool any(bool f(element)) { | |
| 45 for(var i = 0; i <= count; i++) { | |
| 46 if(f(i)) return true; | |
| 47 } | |
| 48 return false; | |
| 49 } | |
| 50 | |
| 51 String toString() => "<[$count]>"; | |
| 52 | |
| 53 Iterator get iterator { | |
| 54 return new SimpleIterator(count); | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 class SimpleIterator implements Iterator { | |
| 59 int _count; | |
| 60 int _current; | |
| 61 | |
| 62 SimpleIterator(this._count); | |
| 63 | |
| 64 bool moveNext() { | |
| 65 if (_count > 0) { | |
| 66 _current = _count; | |
| 67 _count--; | |
| 68 return true; | |
| 69 } | |
| 70 _current = null; | |
| 71 return false; | |
| 72 } | |
| 73 | |
| 74 get current => _current; | |
| 75 } | |
| 76 | 12 |
| 77 void main() { | 13 void main() { |
| 78 | 14 |
| 79 initUtils(); | 15 initUtils(); |
| 80 | 16 |
| 81 // Core matchers | 17 // Core matchers |
| 82 | 18 |
| 83 group('Core matchers', () { | 19 group('Core matchers', () { |
| 84 | 20 |
| 85 test('isTrue', () { | 21 test('isTrue', () { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 test('throwsA', () { | 76 test('throwsA', () { |
| 141 shouldPass(doesThrow, throwsA(equals('X'))); | 77 shouldPass(doesThrow, throwsA(equals('X'))); |
| 142 shouldFail(doesThrow, throwsA(equals('Y')), | 78 shouldFail(doesThrow, throwsA(equals('Y')), |
| 143 matches( | 79 matches( |
| 144 r"Expected: throws an exception which matches 'Y' +" | 80 r"Expected: throws an exception which matches 'Y' +" |
| 145 r"But: exception 'X' does not match 'Y'\." | 81 r"But: exception 'X' does not match 'Y'\." |
| 146 r"Actual: <Closure(: \(dynamic\) => dynamic " | 82 r"Actual: <Closure(: \(dynamic\) => dynamic " |
| 147 r"from Function 'doesThrow': static\.)?>")); | 83 r"from Function 'doesThrow': static\.)?>")); |
| 148 }); | 84 }); |
| 149 | 85 |
| 150 test('throwsFormatException', () { | |
| 151 shouldPass(() { throw new FormatException(''); }, | |
| 152 throwsFormatException); | |
| 153 shouldFail(() { throw new Exception(); }, | |
| 154 throwsFormatException, | |
| 155 matches( | |
| 156 r"Expected: throws an exception which matches FormatException +" | |
| 157 r"But: exception \?:<Exception> does not match FormatException\." | |
| 158 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 159 }); | |
| 160 | |
| 161 test('throwsArgumentError', () { | |
| 162 shouldPass(() { throw new ArgumentError(''); }, | |
| 163 throwsArgumentError); | |
| 164 shouldFail(() { throw new Exception(); }, | |
| 165 throwsArgumentError, | |
| 166 matches( | |
| 167 r"Expected: throws an exception which matches ArgumentError +" | |
| 168 r"But: exception \?:<Exception> does not match " | |
| 169 r"ArgumentError\." | |
| 170 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 171 }); | |
| 172 | |
| 173 test('throwsRangeError', () { | |
| 174 shouldPass(() { throw new RangeError(0); }, | |
| 175 throwsRangeError); | |
| 176 shouldFail(() { throw new Exception(); }, | |
| 177 throwsRangeError, | |
| 178 matches( | |
| 179 r"Expected: throws an exception which matches RangeError +" | |
| 180 r"But: exception \?:<Exception> does not match RangeError\." | |
| 181 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 182 }); | |
| 183 | |
| 184 test('throwsNoSuchMethodError', () { | |
| 185 shouldPass(() { throw new NoSuchMethodError(null, '', null, null); }, | |
| 186 throwsNoSuchMethodError); | |
| 187 shouldFail(() { throw new Exception(); }, | |
| 188 throwsNoSuchMethodError, | |
| 189 matches( | |
| 190 r"Expected: throws an exception which matches NoSuchMethodError +" | |
| 191 r"But: exception \?:<Exception> does not match " | |
| 192 r"NoSuchMethodError\." | |
| 193 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 194 }); | |
| 195 | |
| 196 test('throwsUnimplementedError', () { | |
| 197 shouldPass(() { throw new UnimplementedError(''); }, | |
| 198 throwsUnimplementedError); | |
| 199 shouldFail(() { throw new Exception(); }, | |
| 200 throwsUnimplementedError, | |
| 201 matches( | |
| 202 r"Expected: throws an exception which matches " | |
| 203 r"UnimplementedError +" | |
| 204 r"But: exception \?:<Exception> does not match " | |
| 205 r"UnimplementedError\." | |
| 206 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 207 }); | |
| 208 | |
| 209 test('throwsUnsupportedError', () { | |
| 210 shouldPass(() { throw new UnsupportedError(''); }, | |
| 211 throwsUnsupportedError); | |
| 212 shouldFail(() { throw new Exception(); }, | |
| 213 throwsUnsupportedError, | |
| 214 matches( | |
| 215 r"Expected: throws an exception which matches UnsupportedError +" | |
| 216 r"But: exception \?:<Exception> does not match " | |
| 217 r"UnsupportedError\." | |
| 218 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 219 }); | |
| 220 | |
| 221 test('throwsStateError', () { | |
| 222 shouldPass(() { throw new StateError(''); }, | |
| 223 throwsStateError); | |
| 224 shouldFail(() { throw new Exception(); }, | |
| 225 throwsStateError, | |
| 226 matches( | |
| 227 r"Expected: throws an exception which matches StateError +" | |
| 228 r"But: exception \?:<Exception> does not match " | |
| 229 r"StateError\." | |
| 230 r"Actual: <Closure(: \(dynamic\) => dynamic)?>")); | |
| 231 }); | |
| 232 | |
| 233 test('returnsNormally', () { | 86 test('returnsNormally', () { |
| 234 shouldPass(doesNotThrow, returnsNormally); | 87 shouldPass(doesNotThrow, returnsNormally); |
| 235 shouldFail(doesThrow, returnsNormally, | 88 shouldFail(doesThrow, returnsNormally, |
| 236 matches( | 89 matches( |
| 237 r"Expected: return normally +But: threw 'X'\." | 90 r"Expected: return normally +But: threw 'X'\." |
| 238 r"Actual: <Closure(: \(dynamic\) => dynamic " | 91 r"Actual: <Closure(: \(dynamic\) => dynamic " |
| 239 r"from Function 'doesThrow': static\.)?>")); | 92 r"from Function 'doesThrow': static\.)?>")); |
| 240 }); | 93 }); |
| 241 | 94 |
| 242 test('hasLength', () { | 95 test('hasLength', () { |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 | 328 |
| 476 test('matches', () { | 329 test('matches', () { |
| 477 shouldPass('c0d', matches('[a-z][0-9][a-z]')); | 330 shouldPass('c0d', matches('[a-z][0-9][a-z]')); |
| 478 shouldPass('c0d', matches(new RegExp('[a-z][0-9][a-z]'))); | 331 shouldPass('c0d', matches(new RegExp('[a-z][0-9][a-z]'))); |
| 479 shouldFail('cOd', matches('[a-z][0-9][a-z]'), | 332 shouldFail('cOd', matches('[a-z][0-9][a-z]'), |
| 480 "Expected: match '[a-z][0-9][a-z]' But: was 'cOd'."); | 333 "Expected: match '[a-z][0-9][a-z]' But: was 'cOd'."); |
| 481 }); | 334 }); |
| 482 }); | 335 }); |
| 483 | 336 |
| 484 group('Iterable Matchers', () { | 337 group('Iterable Matchers', () { |
| 485 test('isEmpty', () { | |
| 486 var d = new SimpleIterable(0); | |
| 487 var e = new SimpleIterable(1); | |
| 488 shouldPass(d, isEmpty); | |
| 489 shouldFail(e, isEmpty, "Expected: empty But: was SimpleIterable:[1]."); | |
| 490 }); | |
| 491 | |
| 492 test('contains', () { | |
| 493 var d = new SimpleIterable(3); | |
| 494 shouldPass(d, contains(2)); | |
| 495 shouldFail(d, contains(5), | |
| 496 "Expected: contains <5> " | |
| 497 "But: was SimpleIterable:[3, 2, 1]."); | |
| 498 }); | |
| 499 }); | |
| 500 | |
| 501 group('Iterable Matchers', () { | |
| 502 | 338 |
| 503 test('isEmpty', () { | 339 test('isEmpty', () { |
| 504 shouldPass([], isEmpty); | 340 shouldPass([], isEmpty); |
| 505 shouldFail([1], isEmpty, "Expected: empty But: was [1]."); | 341 shouldFail([1], isEmpty, "Expected: empty But: was [1]."); |
| 506 }); | 342 }); |
| 507 | 343 |
| 508 test('contains', () { | 344 test('contains', () { |
| 509 var d = [1, 2]; | 345 var d = [1, 2]; |
| 510 shouldPass(d, contains(1)); | 346 shouldPass(d, contains(1)); |
| 511 shouldFail(d, contains(0), "Expected: contains <0> But: was [1, 2]."); | 347 shouldFail(d, contains(0), "Expected: contains <0> But: was [1, 2]."); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 }); | 603 }); |
| 768 }); | 604 }); |
| 769 | 605 |
| 770 group('Predicate Matchers', () { | 606 group('Predicate Matchers', () { |
| 771 test('isInstanceOf', () { | 607 test('isInstanceOf', () { |
| 772 shouldFail(0, predicate((x) => x is String, "an instance of String"), | 608 shouldFail(0, predicate((x) => x is String, "an instance of String"), |
| 773 "Expected: an instance of String But: was <0>."); | 609 "Expected: an instance of String But: was <0>."); |
| 774 shouldPass('cow', predicate((x) => x is String, "an instance of String")); | 610 shouldPass('cow', predicate((x) => x is String, "an instance of String")); |
| 775 }); | 611 }); |
| 776 }); | 612 }); |
| 777 | |
| 778 group('Feature Matchers', () { | |
| 779 test("Feature Matcher", () { | |
| 780 var w = new Widget(); | |
| 781 w.price = 10; | |
| 782 shouldPass(w, new HasPrice(10)); | |
| 783 shouldPass(w, new HasPrice(greaterThan(0))); | |
| 784 shouldFail(w, new HasPrice(greaterThan(10)), | |
| 785 "Expected: Widget with a price that is a value greater than <10> " | |
| 786 "But: price was <10>. " | |
| 787 "Actual: <Instance of 'Widget'>"); | |
| 788 }); | |
| 789 }); | |
| 790 } | 613 } |
| 791 | 614 |
| OLD | NEW |