Index: lib/unittest/collection_matchers.dart |
=================================================================== |
--- lib/unittest/collection_matchers.dart (revision 0) |
+++ lib/unittest/collection_matchers.dart (revision 0) |
@@ -0,0 +1,174 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+// Collection matchers match against a collection. We add this intermediate |
Bob Nystrom
2012/05/30 23:23:51
Make this a doc comment for the class:
/**
* Col
gram
2012/06/01 17:33:15
Done.
|
+// class to give better mismatch error messages than the base Matcher class. |
+ |
+class _CollectionMatcher extends Matcher { |
+ IDescription describeMismatch(item, IDescription mismatchDescription) { |
+ if (!(item is Collection)) { |
Bob Nystrom
2012/05/30 23:23:51
if (item is !Collection)
gram
2012/06/01 17:33:15
Done.
|
+ return mismatchDescription. |
+ appendDescriptionOf(item). |
+ append(' not a collection'); |
+ } else { |
+ return super.describeMismatch(item, mismatchDescription); |
+ } |
+ } |
+} |
+//----------------------------------------------------------- |
Bob Nystrom
2012/05/30 23:23:51
I don't think we need a comments for structure. Wh
gram
2012/06/01 17:33:15
Done.
|
+/** |
+ * This returns a matcher that matches empty collections. |
Bob Nystrom
2012/05/30 23:23:51
"This returns" -> "Returns"
Here and elsewhere. W
gram
2012/06/01 17:33:15
Done.
|
+ */ |
+IMatcher emptyCollection() => new _EmptyCollection(); |
Bob Nystrom
2012/05/30 23:23:51
Make this a variable so you don't need the ():
fi
gram
2012/06/01 17:33:15
Done.
|
+ |
+class _EmptyCollection extends _CollectionMatcher { |
+ bool matches(collection) { |
Bob Nystrom
2012/05/30 23:23:51
Annotate this to type Collection?
gram
2012/06/01 17:33:15
None of the matches() methods are typed, as they a
Bob Nystrom
2012/06/01 18:22:22
That makes sense.
gram
2012/06/01 22:21:59
Done.
|
+ try { |
+ return collection.isEmpty(); |
+ } catch (var e) { |
Bob Nystrom
2012/05/30 23:23:51
Why are you swallowing exceptions here?
gram
2012/06/01 17:33:15
The idea is that you can pass anything in, and tha
Bob Nystrom
2012/06/01 18:22:22
Is that helpful to users? If I do:
expect(foo, is
gram
2012/06/01 22:21:59
I think we're both partly right. I do think that e
Bob Nystrom
2012/06/01 22:29:00
Perfect. I love it.
|
+ return false; |
+ } |
+ } |
+ |
+ IDescription describe(IDescription description) => |
+ description.append('be empty'); |
+} |
+ |
+//----------------------------------------------------------- |
+/** |
+ * This returns a matcher that matches collection that contains [obj]. |
Bob Nystrom
2012/05/30 23:23:51
"collection" -> "a collection"
gram
2012/06/01 17:33:15
Done.
|
+ */ |
+IMatcher contains(obj) => new _CollectionContains(obj); |
+ |
+class _CollectionContains extends _CollectionMatcher { |
+ |
+ var _val; |
Bob Nystrom
2012/05/30 23:23:51
"_val" -> "_value"
gram
2012/06/01 17:33:15
Done.
|
+ |
+ _CollectionContains(this._val); |
+ |
+ bool matches(item) { |
+ try { |
+ return item.some( (e) => e == _val ); |
Bob Nystrom
2012/05/30 23:23:51
Space like:
return item.some((e) => e == _val);
gram
2012/06/01 17:33:15
Done.
|
+ } catch (var e) { |
+ return false; |
+ } |
+ } |
+ IDescription describe(IDescription description) => |
Bob Nystrom
2012/05/30 23:23:51
Maybe a blank line before this one?
gram
2012/06/01 17:33:15
Done.
|
+ description.append('contains ').appendDescriptionOf(_val); |
+} |
+ |
+//----------------------------------------------------------- |
+/** |
+ * This returns a matcher which matches collections in which all elements |
+ * match the given [matcher]. |
+ */ |
+IMatcher everyElement(matcher) => new _EveryElement(wrapMatcher(matcher)); |
+ |
+class _EveryElement extends _CollectionMatcher { |
+ Matcher _matcher; |
+ |
+ _EveryElement(Matcher this._matcher); |
Bob Nystrom
2012/05/30 23:23:51
We don't type annotate "this." constructor params
gram
2012/06/01 17:33:15
Done.
|
+ |
+ bool matches(item) { |
+ try { |
+ return item.every( (e) => _matcher.matches(e) ); |
Bob Nystrom
2012/05/30 23:23:51
No spaces around lambda fn.
gram
2012/06/01 17:33:15
Done.
|
+ } catch (var e) { |
+ return false; |
+ } |
+ } |
+ IDescription describe(IDescription description) => |
+ description.append('every element '). |
+ appendDescriptionOf(_matcher); |
+} |
+ |
+//----------------------------------------------------------- |
+/** |
+ * This returns a matcher which matches collections in which at least one |
+ * element matches the given [matcher]. |
+ */ |
+IMatcher someElement(matcher) => new _SomeElement(wrapMatcher(matcher)); |
+ |
+class _SomeElement extends _CollectionMatcher { |
+ Matcher _matcher; |
+ |
+ _SomeElement(Matcher this._matcher); |
+ |
+ bool matches(item) { |
+ try { |
+ return item.some( (e) => _matcher.matches(e) ); |
+ } catch (var e) { |
+ return false; |
+ } |
+ } |
+ IDescription describe(IDescription description) => |
+ description.append('some element '). |
+ appendDescriptionOf(_matcher); |
+} |
+ |
+//----------------------------------------------------------- |
+/** |
+ * This returns a matcher which matches collections that have the same |
+ * length and the same elements as [expected], and in the same order. |
+ */ |
+ |
+IMatcher orderedEquals(expected) => new _OrderedEquals(new List.from(expected)); |
Bob Nystrom
2012/05/30 23:23:51
Why new List.from() here?
Can "expected" be annot
gram
2012/06/01 17:33:15
Done.
gram
2012/06/01 17:33:15
We need at least one of the two to be indexable. I
Bob Nystrom
2012/06/01 18:22:22
Is this comment still accurate? It looks like the
|
+ |
+class _OrderedEquals extends Matcher { |
+ var _expected; |
+ |
+ _OrderedEquals(this._expected); |
+ |
+ bool matches(item) { |
+ try { |
+ List actual = new List.from(item); |
Bob Nystrom
2012/05/30 23:23:51
"List" -> "var".
We rarely annotate locals.
gram
2012/06/01 17:33:15
Done.
|
+ if (_expected.length == actual.length) { |
Bob Nystrom
2012/05/30 23:23:51
It would be nice if this worked with any Iterable
gram
2012/06/01 17:33:15
Done.
|
+ for (int i = 0; i < _expected.length; i++) { |
+ if (_expected[i] != actual[i]) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ } catch (var e) { |
+ } |
+ return false; |
+ } |
+ |
+ IDescription describe(IDescription description) => |
+ description.append('equals '). |
+ appendDescriptionOf(_expected).append(' ordered'); |
+} |
+ |
+//----------------------------------------------------------- |
+/** |
+ * This returns a matcher which matches collections that have the same |
+ * length and the same elements as [expected], but not necessarily in |
+ * the same order. |
+ */ |
+IMatcher unorderedEquals(expected) => |
Bob Nystrom
2012/05/30 23:23:51
Can this be type annotated?
gram
2012/06/01 17:33:15
Done.
|
+ new _UnorderedEquals(new Set.from(expected)); |
Bob Nystrom
2012/05/30 23:23:51
Does this mean all items in expected must be hasha
gram
2012/06/01 17:33:15
I rewrote it so that isn't necessary. It is O(n^2)
|
+ |
+class _UnorderedEquals extends Matcher { |
+ var _expected; |
+ |
+ _UnorderedEquals(this._expected); |
+ |
+ bool matches(item) { |
+ try { |
+ Set items = new Set.from(item); |
Bob Nystrom
2012/05/30 23:23:51
"Set" -> "var".
gram
2012/06/01 17:33:15
Done.
|
+ Set missing = new Set.from(_expected); |
+ missing.removeAll(items); |
+ Set extra = items; |
+ extra.removeAll(_expected); |
+ return missing.isEmpty() && extra.isEmpty(); |
+ } catch (var e) { |
+ return false; |
+ } |
+ } |
+ |
+ IDescription describe(IDescription description) => |
+ description.append('equals '). |
+ appendDescriptionOf(_expected).append(' unordered'); |
+} |
+ |