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 part of matcher; | 5 library matcher.expect; |
6 | 6 |
7 /** The objects thrown by the default failure handler. */ | 7 import 'core_matchers.dart'; |
| 8 import 'description.dart'; |
| 9 import 'interfaces.dart'; |
| 10 |
| 11 /// The objects thrown by the default failure handler. |
8 class TestFailure extends Error { | 12 class TestFailure extends Error { |
9 final String message; | 13 final String message; |
10 | 14 |
11 TestFailure(this.message); | 15 TestFailure(this.message); |
12 | 16 |
13 String toString() => message; | 17 String toString() => message; |
14 } | 18 } |
15 | 19 |
16 /** | 20 /// Useful utility for nesting match states. |
17 * Useful utility for nesting match states. | |
18 */ | |
19 | 21 |
20 void addStateInfo(Map matchState, Map values) { | 22 void addStateInfo(Map matchState, Map values) { |
21 var innerState = new Map.from(matchState); | 23 var innerState = new Map.from(matchState); |
22 matchState.clear(); | 24 matchState.clear(); |
23 matchState['state'] = innerState; | 25 matchState['state'] = innerState; |
24 matchState.addAll(values); | 26 matchState.addAll(values); |
25 } | 27 } |
26 | 28 |
27 /** | 29 /// Some matchers, like those for Futures and exception testing, |
28 * Some matchers, like those for Futures and exception testing, | 30 /// can fail in asynchronous sections, and throw exceptions. |
29 * can fail in asynchronous sections, and throw exceptions. | 31 /// A user of this library will typically want to catch and handle |
30 * A user of this library will typically want to catch and handle | 32 /// such exceptions. The [wrapAsync] property is a function that |
31 * such exceptions. The [wrapAsync] property is a function that | 33 /// can wrap callbacks used by these Matchers so that they can be |
32 * can wrap callbacks used by these Matchers so that they can be | 34 /// used safely. For example, the unittest library will set this |
33 * used safely. For example, the unittest library will set this | 35 /// to be `expectAsync`. By default this is an identity function. |
34 * to be `expectAsync`. By default this is an identity function. | |
35 */ | |
36 Function wrapAsync = (Function f, [id]) => f; | 36 Function wrapAsync = (Function f, [id]) => f; |
37 | 37 |
38 /** | 38 /// This is the main assertion function. It asserts that [actual] |
39 * This is the main assertion function. It asserts that [actual] | 39 /// matches the [matcher]. [reason] is optional and is typically not |
40 * matches the [matcher]. [reason] is optional and is typically not | 40 /// supplied, as a reason is generated from the matcher; if [reason] |
41 * supplied, as a reason is generated from the matcher; if [reason] | 41 /// is included it is appended to the reason generated by the matcher. |
42 * is included it is appended to the reason generated by the matcher. | 42 /// |
43 * | 43 /// [matcher] can be a value in which case it will be wrapped in an |
44 * [matcher] can be a value in which case it will be wrapped in an | 44 /// [equals] matcher. |
45 * [equals] matcher. | 45 /// |
46 * | 46 /// If the assertion fails, then the default behavior is to throw a |
47 * If the assertion fails, then the default behavior is to throw a | 47 /// [TestFailure], but this behavior can be changed by calling |
48 * [TestFailure], but this behavior can be changed by calling | 48 /// [configureExpectFailureHandler] and providing an alternative handler that |
49 * [configureExpectFailureHandler] and providing an alternative handler that | 49 /// implements the [IFailureHandler] interface. It is also possible to |
50 * implements the [IFailureHandler] interface. It is also possible to | 50 /// pass a [failureHandler] to [expect] as a final parameter for fine- |
51 * pass a [failureHandler] to [expect] as a final parameter for fine- | 51 /// grained control. |
52 * grained control. | 52 /// |
53 * | 53 /// In some cases extra diagnostic info can be produced on failure (for |
54 * In some cases extra diagnostic info can be produced on failure (for | 54 /// example, stack traces on mismatched exceptions). To enable these, |
55 * example, stack traces on mismatched exceptions). To enable these, | 55 /// [verbose] should be specified as true; |
56 * [verbose] should be specified as true; | |
57 */ | |
58 void expect(actual, matcher, {String reason, FailureHandler failureHandler, | 56 void expect(actual, matcher, {String reason, FailureHandler failureHandler, |
59 bool verbose : false}) { | 57 bool verbose : false}) { |
60 matcher = wrapMatcher(matcher); | 58 matcher = wrapMatcher(matcher); |
61 bool doesMatch; | 59 bool doesMatch; |
62 var matchState = {}; | 60 var matchState = {}; |
63 try { | 61 try { |
64 doesMatch = matcher.matches(actual, matchState); | 62 doesMatch = matcher.matches(actual, matchState); |
65 } catch (e, trace) { | 63 } catch (e, trace) { |
66 doesMatch = false; | 64 doesMatch = false; |
67 if (reason == null) { | 65 if (reason == null) { |
68 reason = '${(e is String) ? e : e.toString()} at $trace'; | 66 reason = '${(e is String) ? e : e.toString()} at $trace'; |
69 } | 67 } |
70 } | 68 } |
71 if (!doesMatch) { | 69 if (!doesMatch) { |
72 if (failureHandler == null) { | 70 if (failureHandler == null) { |
73 failureHandler = getOrCreateExpectFailureHandler(); | 71 failureHandler = getOrCreateExpectFailureHandler(); |
74 } | 72 } |
75 failureHandler.failMatch(actual, matcher, reason, matchState, verbose); | 73 failureHandler.failMatch(actual, matcher, reason, matchState, verbose); |
76 } | 74 } |
77 } | 75 } |
78 | 76 |
79 void fail(String message, {FailureHandler failureHandler}) { | 77 void fail(String message, {FailureHandler failureHandler}) { |
80 if (failureHandler == null) { | 78 if (failureHandler == null) { |
81 failureHandler = getOrCreateExpectFailureHandler(); | 79 failureHandler = getOrCreateExpectFailureHandler(); |
82 } | 80 } |
83 failureHandler.fail(message); | 81 failureHandler.fail(message); |
84 } | 82 } |
85 | 83 |
86 /** | 84 /// Takes an argument and returns an equivalent matcher. |
87 * Takes an argument and returns an equivalent matcher. | 85 /// If the argument is already a matcher this does nothing, |
88 * If the argument is already a matcher this does nothing, | 86 /// else if the argument is a function, it generates a predicate |
89 * else if the argument is a function, it generates a predicate | 87 /// function matcher, else it generates an equals matcher. |
90 * function matcher, else it generates an equals matcher. | |
91 */ | |
92 Matcher wrapMatcher(x) { | 88 Matcher wrapMatcher(x) { |
93 if (x is Matcher) { | 89 if (x is Matcher) { |
94 return x; | 90 return x; |
95 } else if (x is Function) { | 91 } else if (x is Function) { |
96 return predicate(x); | 92 return predicate(x); |
97 } else { | 93 } else { |
98 return equals(x); | 94 return equals(x); |
99 } | 95 } |
100 } | 96 } |
101 | 97 |
102 // The handler for failed asserts. | 98 // The handler for failed asserts. |
103 FailureHandler _assertFailureHandler = null; | 99 FailureHandler _assertFailureHandler = null; |
104 | 100 |
105 // The default failure handler that throws [TestFailure]s. | 101 // The default failure handler that throws [TestFailure]s. |
106 class DefaultFailureHandler implements FailureHandler { | 102 class DefaultFailureHandler implements FailureHandler { |
107 DefaultFailureHandler() { | 103 DefaultFailureHandler() { |
108 if (_assertErrorFormatter == null) { | 104 if (_assertErrorFormatter == null) { |
109 _assertErrorFormatter = _defaultErrorFormatter; | 105 _assertErrorFormatter = _defaultErrorFormatter; |
110 } | 106 } |
111 } | 107 } |
112 void fail(String reason) { | 108 void fail(String reason) { |
113 throw new TestFailure(reason); | 109 throw new TestFailure(reason); |
114 } | 110 } |
115 void failMatch(actual, Matcher matcher, String reason, | 111 void failMatch(actual, Matcher matcher, String reason, |
116 Map matchState, bool verbose) { | 112 Map matchState, bool verbose) { |
117 fail(_assertErrorFormatter(actual, matcher, reason, matchState, verbose)); | 113 fail(_assertErrorFormatter(actual, matcher, reason, matchState, verbose)); |
118 } | 114 } |
119 } | 115 } |
120 | 116 |
121 /** | 117 /// Changes or resets to the default the failure handler for expect() |
122 * Changes or resets to the default the failure handler for expect() | 118 /// [handler] is a reference to the new handler; if this is omitted |
123 * [handler] is a reference to the new handler; if this is omitted | 119 /// or null then the failure handler is reset to the default, which |
124 * or null then the failure handler is reset to the default, which | 120 /// throws [TestFailure]s on [expect] assertion failures. |
125 * throws [TestFailure]s on [expect] assertion failures. | |
126 */ | |
127 void configureExpectFailureHandler([FailureHandler handler = null]) { | 121 void configureExpectFailureHandler([FailureHandler handler = null]) { |
128 if (handler == null) { | 122 if (handler == null) { |
129 handler = new DefaultFailureHandler(); | 123 handler = new DefaultFailureHandler(); |
130 } | 124 } |
131 _assertFailureHandler = handler; | 125 _assertFailureHandler = handler; |
132 } | 126 } |
133 | 127 |
134 FailureHandler getOrCreateExpectFailureHandler() { | 128 FailureHandler getOrCreateExpectFailureHandler() { |
135 if (_assertFailureHandler == null) { | 129 if (_assertFailureHandler == null) { |
136 configureExpectFailureHandler(); | 130 configureExpectFailureHandler(); |
(...skipping 16 matching lines...) Expand all Loading... |
153 | 147 |
154 if (mismatchDescription.length > 0) { | 148 if (mismatchDescription.length > 0) { |
155 description.add(' Which: ${mismatchDescription}\n'); | 149 description.add(' Which: ${mismatchDescription}\n'); |
156 } | 150 } |
157 if (reason != null) { | 151 if (reason != null) { |
158 description.add(reason).add('\n'); | 152 description.add(reason).add('\n'); |
159 } | 153 } |
160 return description.toString(); | 154 return description.toString(); |
161 } | 155 } |
162 | 156 |
163 /** | 157 /// Changes or resets to default the failure message formatter for expect(). |
164 * Changes or resets to default the failure message formatter for expect(). | 158 /// [formatter] is a reference to the new formatter; if this is omitted or |
165 * [formatter] is a reference to the new formatter; if this is omitted or | 159 /// null then the failure formatter is reset to the default. The new |
166 * null then the failure formatter is reset to the default. The new | 160 /// formatter is returned; this allows custom expect handlers to easily |
167 * formatter is returned; this allows custom expect handlers to easily | 161 /// get a reference to the default formatter. |
168 * get a reference to the default formatter. | |
169 */ | |
170 ErrorFormatter configureExpectFormatter([ErrorFormatter formatter = null]) { | 162 ErrorFormatter configureExpectFormatter([ErrorFormatter formatter = null]) { |
171 if (formatter == null) { | 163 if (formatter == null) { |
172 formatter = _defaultErrorFormatter; | 164 formatter = _defaultErrorFormatter; |
173 } | 165 } |
174 return _assertErrorFormatter = formatter; | 166 return _assertErrorFormatter = formatter; |
175 } | 167 } |
176 | |
OLD | NEW |