OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library matcher.expect; |
| 6 |
| 7 import 'core_matchers.dart'; |
| 8 import 'description.dart'; |
| 9 import 'interfaces.dart'; |
| 10 import 'util.dart'; |
| 11 |
| 12 /// The objects thrown by the default failure handler. |
| 13 class TestFailure extends Error { |
| 14 final String message; |
| 15 |
| 16 TestFailure(this.message); |
| 17 |
| 18 String toString() => message; |
| 19 } |
| 20 |
| 21 /// Failed matches are reported using a default IFailureHandler. |
| 22 /// The default implementation simply throws [TestFailure]s; |
| 23 /// this can be replaced by some other implementation of |
| 24 /// IFailureHandler by calling configureExpectHandler. |
| 25 abstract class FailureHandler { |
| 26 /// This handles failures given a textual decription |
| 27 void fail(String reason); |
| 28 |
| 29 /// This handles failures given the actual [value], the [matcher] |
| 30 /// the [reason] (argument from [expect]), some additonal [matchState] |
| 31 /// generated by the [matcher], and a verbose flag which controls in |
| 32 /// some cases how much [matchState] information is used. It will use |
| 33 /// these to create a detailed error message (typically by calling |
| 34 /// an [ErrorFormatter]) and then call [fail] with this message. |
| 35 void failMatch( |
| 36 actual, Matcher matcher, String reason, Map matchState, bool verbose); |
| 37 } |
| 38 |
| 39 /// The ErrorFormatter type is used for functions that |
| 40 /// can be used to build up error reports upon [expect] failures. |
| 41 /// There is one built-in implementation ([defaultErrorFormatter]) |
| 42 /// which is used by the default failure handler. If the failure handler |
| 43 /// is replaced it may be desirable to replace the [stringDescription] |
| 44 /// error formatter with another. |
| 45 typedef String ErrorFormatter( |
| 46 actual, Matcher matcher, String reason, Map matchState, bool verbose); |
| 47 |
| 48 /// This Function is used by certain Matchers to catch certain exceptions. |
| 49 /// |
| 50 /// Some matchers, like those for Futures and exception testing, |
| 51 /// can fail in asynchronous sections, and throw exceptions. |
| 52 /// A user of this library will typically want to catch and handle |
| 53 /// such exceptions. The [wrapAsync] property is a function that |
| 54 /// can wrap callbacks used by these Matchers so that they can be |
| 55 /// used safely. For example, the unittest library will set this |
| 56 /// to be `expectAsync`. By default this is an identity function. |
| 57 Function wrapAsync = (Function f, [id]) => f; |
| 58 |
| 59 /// Assert that [actual] matches [matcher]. |
| 60 /// |
| 61 /// This is the main assertion function. [reason] is optional and is typically |
| 62 /// not supplied, as a reason is generated from the matcher; if [reason] |
| 63 /// is included it is appended to the reason generated by the matcher. |
| 64 /// |
| 65 /// [matcher] can be a value in which case it will be wrapped in an |
| 66 /// [equals] matcher. |
| 67 /// |
| 68 /// If the assertion fails, then the default behavior is to throw a |
| 69 /// [TestFailure], but this behavior can be changed by calling |
| 70 /// [configureExpectFailureHandler] and providing an alternative handler that |
| 71 /// implements the [IFailureHandler] interface. It is also possible to |
| 72 /// pass a [failureHandler] to [expect] as a final parameter for fine- |
| 73 /// grained control. |
| 74 /// |
| 75 /// In some cases extra diagnostic info can be produced on failure (for |
| 76 /// example, stack traces on mismatched exceptions). To enable these, |
| 77 /// [verbose] should be specified as true; |
| 78 void expect(actual, matcher, |
| 79 {String reason, FailureHandler failureHandler, bool verbose: false}) { |
| 80 matcher = wrapMatcher(matcher); |
| 81 bool doesMatch; |
| 82 var matchState = {}; |
| 83 try { |
| 84 doesMatch = matcher.matches(actual, matchState); |
| 85 } catch (e, trace) { |
| 86 doesMatch = false; |
| 87 if (reason == null) { |
| 88 reason = '${(e is String) ? e : e.toString()} at $trace'; |
| 89 } |
| 90 } |
| 91 if (!doesMatch) { |
| 92 if (failureHandler == null) { |
| 93 failureHandler = getOrCreateExpectFailureHandler(); |
| 94 } |
| 95 failureHandler.failMatch(actual, matcher, reason, matchState, verbose); |
| 96 } |
| 97 } |
| 98 |
| 99 void fail(String message, {FailureHandler failureHandler}) { |
| 100 if (failureHandler == null) { |
| 101 failureHandler = getOrCreateExpectFailureHandler(); |
| 102 } |
| 103 failureHandler.fail(message); |
| 104 } |
| 105 |
| 106 // The handler for failed asserts. |
| 107 FailureHandler _assertFailureHandler = null; |
| 108 |
| 109 // The default failure handler that throws [TestFailure]s. |
| 110 class DefaultFailureHandler implements FailureHandler { |
| 111 DefaultFailureHandler() { |
| 112 if (_assertErrorFormatter == null) { |
| 113 _assertErrorFormatter = _defaultErrorFormatter; |
| 114 } |
| 115 } |
| 116 void fail(String reason) { |
| 117 throw new TestFailure(reason); |
| 118 } |
| 119 void failMatch( |
| 120 actual, Matcher matcher, String reason, Map matchState, bool verbose) { |
| 121 fail(_assertErrorFormatter(actual, matcher, reason, matchState, verbose)); |
| 122 } |
| 123 } |
| 124 |
| 125 /// Changes the default failure handler for [expect]. |
| 126 /// |
| 127 /// [handler] is a reference to the new handler; if this is omitted |
| 128 /// or null then the failure handler is reset to the default, which |
| 129 /// throws [TestFailure]s on [expect] assertion failures. |
| 130 void configureExpectFailureHandler([FailureHandler handler = null]) { |
| 131 if (handler == null) { |
| 132 handler = new DefaultFailureHandler(); |
| 133 } |
| 134 _assertFailureHandler = handler; |
| 135 } |
| 136 |
| 137 FailureHandler getOrCreateExpectFailureHandler() { |
| 138 if (_assertFailureHandler == null) { |
| 139 configureExpectFailureHandler(); |
| 140 } |
| 141 return _assertFailureHandler; |
| 142 } |
| 143 |
| 144 // The error message formatter for failed asserts. |
| 145 ErrorFormatter _assertErrorFormatter = null; |
| 146 |
| 147 // The default error formatter implementation. |
| 148 String _defaultErrorFormatter( |
| 149 actual, Matcher matcher, String reason, Map matchState, bool verbose) { |
| 150 var description = new StringDescription(); |
| 151 description.add('Expected: ').addDescriptionOf(matcher).add('\n'); |
| 152 description.add(' Actual: ').addDescriptionOf(actual).add('\n'); |
| 153 |
| 154 var mismatchDescription = new StringDescription(); |
| 155 matcher.describeMismatch(actual, mismatchDescription, matchState, verbose); |
| 156 |
| 157 if (mismatchDescription.length > 0) { |
| 158 description.add(' Which: ${mismatchDescription}\n'); |
| 159 } |
| 160 if (reason != null) { |
| 161 description.add(reason).add('\n'); |
| 162 } |
| 163 return description.toString(); |
| 164 } |
| 165 |
| 166 /// Changes the failure message formatter for expect(). |
| 167 /// |
| 168 /// [formatter] is a reference to the new formatter; if this is omitted or |
| 169 /// null then the failure formatter is reset to the default. The new |
| 170 /// formatter is returned; this allows custom expect handlers to easily |
| 171 /// get a reference to the default formatter. |
| 172 ErrorFormatter configureExpectFormatter([ErrorFormatter formatter = null]) { |
| 173 if (formatter == null) { |
| 174 formatter = _defaultErrorFormatter; |
| 175 } |
| 176 return _assertErrorFormatter = formatter; |
| 177 } |
OLD | NEW |