From ab1aba5a9a97524645fa6a232fb1df397cb0355a Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Thu, 17 Dec 2009 23:57:39 -0700 Subject: Added Fuzzy docstrings; make-test now runs doctests in tests/*; fixed 'existant' mispelling --- ipaserver/install/ldapupdate.py | 2 +- make-test | 1 + tests/test_install/test_updates.py | 2 +- tests/test_util.py | 2 +- tests/test_xmlrpc/test_group_plugin.py | 24 ++++---- tests/test_xmlrpc/test_pwpolicy.py | 2 +- tests/util.py | 105 ++++++++++++++++++++++++++++----- 7 files changed, 106 insertions(+), 32 deletions(-) diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py index ad2067c09..c03459187 100644 --- a/ipaserver/install/ldapupdate.py +++ b/ipaserver/install/ldapupdate.py @@ -566,7 +566,7 @@ class LDAPUpdate: self.conn.deleteEntry(dn) self.modified = True except errors.NotFound, e: - logging.info("Deleting non-existant entry %s", e) + logging.info("Deleting non-existent entry %s", e) self.modified = True except errors.DatabaseError, e: logging.error("Delete failed: %s", e) diff --git a/make-test b/make-test index 26785e457..d6d2812cb 100755 --- a/make-test +++ b/make-test @@ -39,6 +39,7 @@ parser.add_option('--pdb-failures', cmd = [nose] + args + [ '-v', '--with-doctest', + '--doctest-tests', '--exclude=plugins', ] if options.stop: diff --git a/tests/test_install/test_updates.py b/tests/test_install/test_updates.py index 7f878b312..38ace5507 100644 --- a/tests/test_install/test_updates.py +++ b/tests/test_install/test_updates.py @@ -158,7 +158,7 @@ class test_update(object): def test_6_update_1(self): """ - Test the updater removing a non-existant value from a multi-valued attribute + Test the updater removing a non-existent value from a multi-valued attribute """ modified = self.updater.update([self.testdir + "6_update.update"]) assert(modified == False) diff --git a/tests/test_util.py b/tests/test_util.py index eca2d672e..8d0db69b3 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -86,7 +86,7 @@ class test_Fuzzy(object): assert inst.re is None def test_repr(self): - s = 'Fuzzy(regex=%r, type=%r, test=%r)' + s = 'Fuzzy(%r, %r, %r)' t = lambda other: 0.0 <= other <= 1.0 inst = self.klass() diff --git a/tests/test_xmlrpc/test_group_plugin.py b/tests/test_xmlrpc/test_group_plugin.py index c33bfa3c9..a6d98f698 100644 --- a/tests/test_xmlrpc/test_group_plugin.py +++ b/tests/test_xmlrpc/test_group_plugin.py @@ -40,21 +40,21 @@ class test_group(Declarative): ################ # create group1: dict( - desc='Try to retrieve non-existant %r' % group1, + desc='Try to retrieve non-existent %r' % group1, command=('group_show', [group1], {}), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to update non-existant %r' % group1, + desc='Try to update non-existent %r' % group1, command=('group_mod', [group1], dict(description=u'Foo')), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to delete non-existant %r' % group1, + desc='Try to delete non-existent %r' % group1, command=('group_del', [group1], {}), expected=errors.NotFound(reason='no such entry'), ), @@ -191,21 +191,21 @@ class test_group(Declarative): ################ # create group2: dict( - desc='Try to retrieve non-existant %r' % group2, + desc='Try to retrieve non-existent %r' % group2, command=('group_show', [group2], {}), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to update non-existant %r' % group2, + desc='Try to update non-existent %r' % group2, command=('group_mod', [group2], dict(description=u'Foo')), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to delete non-existant %r' % group2, + desc='Try to delete non-existent %r' % group2, command=('group_del', [group2], {}), expected=errors.NotFound(reason='no such entry'), ), @@ -428,21 +428,21 @@ class test_group(Declarative): dict( - desc='Try to delete non-existant %r' % group1, + desc='Try to delete non-existent %r' % group1, command=('group_del', [group1], {}), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to retrieve non-existant %r' % group1, + desc='Try to retrieve non-existent %r' % group1, command=('group_show', [group1], {}), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to update non-existant %r' % group1, + desc='Try to update non-existent %r' % group1, command=('group_mod', [group1], dict(description=u'Foo')), expected=errors.NotFound(reason='no such entry'), ), @@ -463,21 +463,21 @@ class test_group(Declarative): dict( - desc='Try to delete non-existant %r' % group2, + desc='Try to delete non-existent %r' % group2, command=('group_del', [group2], {}), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to retrieve non-existant %r' % group2, + desc='Try to retrieve non-existent %r' % group2, command=('group_show', [group2], {}), expected=errors.NotFound(reason='no such entry'), ), dict( - desc='Try to update non-existant %r' % group2, + desc='Try to update non-existent %r' % group2, command=('group_mod', [group2], dict(description=u'Foo')), expected=errors.NotFound(reason='no such entry'), ), diff --git a/tests/test_xmlrpc/test_pwpolicy.py b/tests/test_xmlrpc/test_pwpolicy.py index 1c2ccd1d8..080f39bf9 100644 --- a/tests/test_xmlrpc/test_pwpolicy.py +++ b/tests/test_xmlrpc/test_pwpolicy.py @@ -81,7 +81,7 @@ class test_pwpolicy(XMLRPC_test): def test_4_pwpolicy_add(self): """ - Add a pwpolicy for a non-existant group + Add a pwpolicy for a non-existent group """ try: api.Command['pwpolicy_add'](group=u'nopwpolicy',cospriority=1,krbminpwdlife=1) diff --git a/tests/util.py b/tests/util.py index d93a967c1..ed8ecadf1 100644 --- a/tests/util.py +++ b/tests/util.py @@ -111,10 +111,82 @@ def assert_equal(val1, val2): class Fuzzy(object): """ - Perform a fuzzy (non-strict) equality test. + Perform a fuzzy (non-strict) equality tests. `Fuzzy` instances will likely be used when comparing nesting data-structures using `assert_deepequal()`. + + By default a `Fuzzy` instance is equal to everything. For example, all of + these evaluate to ``True``: + + >>> Fuzzy() == False + True + >>> 7 == Fuzzy() # Order doesn't matter + True + >>> Fuzzy() == u'Hello False, Lucky 7!' + True + + The first optional argument *regex* is a regular expression pattern to + match. For example, you could match a phone number like this: + + >>> phone = Fuzzy('^\d{3}-\d{3}-\d{4}$') + >>> u'123-456-7890' == phone + True + + Use of a regular expression by default implies the ``unicode`` type, so + comparing with an ``str`` instance will evaluate to ``False``: + + >>> phone.type + + >>> '123-456-7890' == phone + False + + The *type* kwarg allows you to specify a type constraint, so you can force + the above to work on ``str`` instances instead: + + >>> '123-456-7890' == Fuzzy('^\d{3}-\d{3}-\d{4}$', type=str) + True + + You can also use the *type* constraint on its own without the *regex*, for + example: + + >>> 42 == Fuzzy(type=int) + True + >>> 42.0 == Fuzzy(type=int) + False + >>> 42.0 == Fuzzy(type=(int, float)) + True + + Finally the *test* kwarg is an optional callable that will be called to + perform the loose equality test. For example: + + >>> 42 == Fuzzy(test=lambda other: other > 42) + False + >>> 43 == Fuzzy(test=lambda other: other > 42) + True + + You can use *type* and *test* together. For example: + + >>> 43 == Fuzzy(type=float, test=lambda other: other > 42) + False + >>> 42.5 == Fuzzy(type=float, test=lambda other: other > 42) + True + + The *regex*, *type*, and *test* kwargs are all availabel via attributes on + the `Fuzzy` instance: + + >>> fuzzy = Fuzzy('.+', type=str, test=lambda other: True) + >>> fuzzy.regex + '.+' + >>> fuzzy.type + + >>> fuzzy.test # doctest:+ELLIPSIS + at 0x...> + + To aid debugging, `Fuzzy.__repr__()` revealse these kwargs as well: + + >>> fuzzy # doctest:+ELLIPSIS + Fuzzy('.+', , at 0x...>) """ def __init__(self, regex=None, type=None, test=None): @@ -144,7 +216,7 @@ class Fuzzy(object): self.test = test def __repr__(self): - return '%s(regex=%r, type=%r, test=%r)' % ( + return '%s(%r, %r, %r)' % ( self.__class__.__name__, self.regex, self.type, self.test ) @@ -192,26 +264,27 @@ KEYS = """assert_deepequal: dict keys mismatch. path = %r""" -def assert_deepequal(expected, got, src='', stack=tuple()): +def assert_deepequal(expected, got, doc='', stack=tuple()): """ Recursively check for type and equality. If the tests fails, it will raise an ``AssertionError`` with detailed information, including the path to the offending value. For example: - >>> expected = [u'hello', dict(naughty=u'nurse')] - >>> got = [u'hello', dict(naughty='nurse')] + >>> expected = [u'Hello', dict(world=u'how are you?')] + >>> got = [u'Hello', dict(world='how are you?')] >>> expected == got True - >>> assert_deepequal(expected, got) + >>> assert_deepequal(expected, got, doc='Testing my nested data') Traceback (most recent call last): ... - AssertionError: assert_deepequal: type(expected) is not type(got): + AssertionError: assert_deepequal: type(expected) is not type(got). + Testing my nested data type(expected) = type(got) = - expected = u'nurse' - got = 'nurse' - path = (1, 'naughty') + expected = u'how are you?' + got = 'how are you?' + path = (1, 'world') """ if isinstance(expected, tuple): expected = list(expected) @@ -219,31 +292,31 @@ def assert_deepequal(expected, got, src='', stack=tuple()): got = list(got) if not (isinstance(expected, Fuzzy) or type(expected) is type(got)): raise AssertionError( - TYPE % (src, type(expected), type(got), expected, got, stack) + TYPE % (doc, type(expected), type(got), expected, got, stack) ) if isinstance(expected, (list, tuple)): if len(expected) != len(got): raise AssertionError( - LEN % (src, len(expected), len(got), expected, got, stack) + LEN % (doc, len(expected), len(got), expected, got, stack) ) for (i, e_sub) in enumerate(expected): g_sub = got[i] - assert_deepequal(e_sub, g_sub, src, stack + (i,)) + assert_deepequal(e_sub, g_sub, doc, stack + (i,)) elif isinstance(expected, dict): missing = set(expected).difference(got) extra = set(got).difference(expected) if missing or extra: raise AssertionError(KEYS % ( - src, sorted(missing), sorted(extra), expected, got, stack + doc, sorted(missing), sorted(extra), expected, got, stack ) ) for key in sorted(expected): e_sub = expected[key] g_sub = got[key] - assert_deepequal(e_sub, g_sub, src, stack + (key,)) + assert_deepequal(e_sub, g_sub, doc, stack + (key,)) elif expected != got: raise AssertionError( - VALUE % (src, expected, got, stack) + VALUE % (doc, expected, got, stack) ) -- cgit