← Back to team overview

testtools-dev team mailing list archive

[Merge] lp:~jml/testtools/same-members into lp:testtools

 

Jonathan Lange has proposed merging lp:~jml/testtools/same-members into lp:testtools.

Requested reviews:
  testtools committers (testtools-committers)

For more details, see:
https://code.launchpad.net/~jml/testtools/same-members/+merge/109331

I saw assertContentEquals in Launchpad's base test case and I thought, "How awful! This ought to be a matcher." And lo, it was so.

This has the advantage of having a nicer error message.

-- 
https://code.launchpad.net/~jml/testtools/same-members/+merge/109331
Your team testtools developers is subscribed to branch lp:testtools.
=== modified file 'testtools/matchers.py'
--- testtools/matchers.py	2012-05-28 14:24:55 +0000
+++ testtools/matchers.py	2012-06-08 11:08:20 +0000
@@ -1277,6 +1277,28 @@
         return Equals(f(self.path)).match(f(other_path))
 
 
+class SameMembers(Matcher):
+    """Matches if two iterators have the same members.
+
+    This is not the same as set equivalence.  The two iterators must be of the
+    same length and have the same repetitions.
+    """
+
+    def __init__(self, expected):
+        super(SameMembers, self).__init__()
+        self.expected = expected
+
+    def __str__(self):
+        return '%s(%r)' % (self.__class__.__name__, self.expected)
+
+    def match(self, observed):
+        expected = sorted(self.expected)
+        observed = sorted(observed)
+        if expected == observed:
+            return
+        return _BinaryMismatch(expected, "elements differ", observed)
+
+
 class HasPermissions(Matcher):
     """Matches if a file has the given permissions.
 

=== modified file 'testtools/tests/test_matchers.py'
--- testtools/tests/test_matchers.py	2012-05-28 14:24:55 +0000
+++ testtools/tests/test_matchers.py	2012-06-08 11:08:20 +0000
@@ -60,6 +60,7 @@
     PathExists,
     Raises,
     raises,
+    SameMembers,
     SamePath,
     StartsWith,
     TarballContains,
@@ -1101,6 +1102,36 @@
         ]
 
 
+class TestSameMembers(TestCase, TestMatchersInterface):
+
+    matches_matcher = SameMembers([1, 1, 2, 3, {'foo': 'bar'}])
+    matches_matches = [
+        [1, 1, 2, 3, {'foo': 'bar'}],
+        [3, {'foo': 'bar'}, 1, 2, 1],
+        [3, 2, 1, {'foo': 'bar'}, 1],
+        (2, {'foo': 'bar'}, 3, 1, 1),
+        ]
+    matches_mismatches = [
+        set([1, 2, 3]),
+        [1, 1, 2, 3, 5],
+        'foo',
+        ]
+
+    describe_examples = [
+        (("elements differ:\n"
+          "reference = ['apple', 'banana', 'canteloupe', 'lemon', 'orange', 'watermelon']\n"
+          "actual    = ['apple', 'banana', 'canteloupe', 'lemon', 'orange', 'sparrow']\n"),
+         ['orange', 'apple', 'banana', 'sparrow', 'lemon', 'canteloupe',],
+         SameMembers(
+             ['apple', 'orange', 'canteloupe', 'watermelon',
+              'lemon', 'banana',])),
+        ]
+
+    str_examples = [
+        ('SameMembers([1, 2, 3])', SameMembers([1, 2, 3])),
+        ]
+
+
 class PathHelpers(object):
 
     def mkdtemp(self):


Follow ups