[Zope-Checkins] CVS: Zope3/src/persistent/tests - test_persistent.py:1.5 persistent.txt:1.2

Chris Withers lists at simplistix.co.uk
Thu Mar 4 03:56:09 EST 2004


Is there a summary of where the decision was made to use DocTests rather than 
real tests with comments or docstrings in the test code?

Personally, I think the doctests below are in danger of looking butt ugly :-S

Chris

Jeremy Hylton wrote:

> Update of /cvs-repository/Zope3/src/persistent/tests
> In directory cvs.zope.org:/tmp/cvs-serv7824/persistent/tests
> 
> Modified Files:
> 	test_persistent.py persistent.txt 
> Log Message:
> Restructure relationship between persistent.txt and test_persistent.py.
> 
> Move some of the test framework code from .py to .txt, and add a more
> detailed comment at the top about the contract between .txt and the
> .py file that uses it.
> 
> Move the interface test into .txt.  I guess it's not so bad.
> 
> Change some tests that displayed the contents of __dict__.  Other
> persistent implementations may have extra state in __dict__.
> 
> Remove B, it is unused.
> 
> Change DocFileSuite() to accept an explicit set of globals.
> 
> Remove the pickling/P2 test, because it was too hard to make work with
> the framework.  Include comment explaining how such a test should be
> added.
> 
> 
> === Zope3/src/persistent/tests/test_persistent.py 1.4 => 1.5 ===
> --- Zope3/src/persistent/tests/test_persistent.py:1.4	Wed Mar  3 07:18:50 2004
> +++ Zope3/src/persistent/tests/test_persistent.py	Wed Mar  3 13:59:42 2004
> @@ -12,23 +12,12 @@
>  #
>  ##############################################################################
>  import doctest
> -import new
>  import os
>  import sys
>  import unittest
>  
> -from persistent import Persistent
> -from persistent.interfaces import IPersistent
>  import persistent.tests
> -
> -try:
> -    import zope.interface
> -except ImportError:
> -    interfaces = False
> -else:
> -    interfaces = True
> -
> -oid = "\0\0\0\0\0\0hi"
> +from persistent import Persistent
>  
>  class P(Persistent):
>      def __init__(self):
> @@ -36,72 +25,16 @@
>      def inc(self):
>          self.x += 1
>  
> -class P2(P):
> -    def __getstate__(self):
> -        return 42
> -    def __setstate__(self, v):
> -        self.v = v
> -
> -class B(Persistent):
> -
> -    __slots__ = ["x", "_p_serial"]
> -
> -    def __init__(self):
> -        self.x = 0
> -
> -    def inc(self):
> -        self.x += 1
> -
> -    def __getstate__(self):
> -        return {'x': self.x}
> -
> -    def __setstate__(self, state):
> -        self.x = state['x']
> -
> -class DM:
> -    def __init__(self):
> -        self.called = 0
> -    def register(self, ob):
> -        self.called += 1
> -    def setstate(self, ob):
> -        ob.__setstate__({'x': 42})
> -
> -class BrokenDM(DM):
> -
> -    def register(self,ob):
> -        self.called += 1
> -        raise NotImplementedError
> -
> -    def setstate(self,ob):
> -        raise NotImplementedError
> -
> -class Test(unittest.TestCase):
> -
> -    # XXX This is the only remaining unittest.  Figure out how to move
> -    # this into doctest?
> -
> -    if interfaces:
> -        def testInterface(self):
> -            self.assert_(IPersistent.isImplementedByInstancesOf(Persistent),
> -                         "%s does not implement IPersistent" % Persistent)
> -            p = Persistent()
> -            self.assert_(IPersistent.isImplementedBy(p),
> -                         "%s does not implement IPersistent" % p)
> -
> -            self.assert_(IPersistent.isImplementedByInstancesOf(P),
> -                         "%s does not implement IPersistent" % P)
> -            p = P()
> -            self.assert_(IPersistent.isImplementedBy(p),
> -                         "%s does not implement IPersistent" % p)
> -
> -def DocFileSuite(path):
> +def DocFileSuite(path, globs=None):
>      # It's not entirely obvious how to connection this single string
>      # with unittest.  For now, re-use the _utest() function that comes
>      # standard with doctest in Python 2.3.  One problem is that the
>      # error indicator doesn't point to the line of the doctest file
>      # that failed.
>      source = open(path).read()
> -    t = doctest.Tester(globs=sys._getframe(1).f_globals)
> +    if globs is None:
> +        globs = sys._getframe(1).f_globals
> +    t = doctest.Tester(globs=globs)
>      def runit():
>          doctest._utest(t, path, source, path, 0)
>      f = unittest.FunctionTestCase(runit, description="doctest from %s" % path)
> @@ -110,7 +43,5 @@
>      return suite
>  
>  def test_suite():
> -    p = os.path.join(persistent.tests.__path__[0], "persistent.txt")
> -    s = unittest.makeSuite(Test)
> -    s.addTest(DocFileSuite(p))
> -    return s
> +    path = os.path.join(persistent.tests.__path__[0], "persistent.txt")
> +    return DocFileSuite(path, {"P": P})
> 
> 
> === Zope3/src/persistent/tests/persistent.txt 1.1 => 1.2 ===
> --- Zope3/src/persistent/tests/persistent.txt:1.1	Tue Mar  2 17:15:14 2004
> +++ Zope3/src/persistent/tests/persistent.txt	Wed Mar  3 13:59:42 2004
> @@ -2,8 +2,42 @@
>  ===============================
>  
>  This document is an extended doc test that covers the basics of the
> -Persistent base class.  It depends on a few base classes defined in
> -test_persistent.py.
> +Persistent base class.  The test expects a class named 'P' to be
> +provided in its globals.  The P class implements the Persistent
> +interface.
> +
> +Test framework
> +--------------
> +
> +The class P needs to behave like ExampleP.  (Note that the code below
> +is *not* part of the tests.)
> +
> +class ExampleP(Persistent):
> +    def __init__(self):
> +        self.x = 0
> +    def inc(self):
> +        self.x += 1
> +
> +The tests use stub data managers.  A data manager is responsible for
> +loading and storing the state of a persistent object.  It's stored in
> +the _p_jar attribute of a persistent object.
> +
> +>>> class DM:
> +...     def __init__(self):
> +...         self.called = 0
> +...     def register(self, ob):
> +...         self.called += 1
> +...     def setstate(self, ob):
> +...         ob.__setstate__({'x': 42})
> +
> +>>> class BrokenDM(DM):
> +...     def register(self,ob):
> +...         self.called += 1
> +...         raise NotImplementedError
> +...     def setstate(self,ob):
> +...         raise NotImplementedError
> +
> +>>> from persistent import Persistent
>  
>  Test Persistent without Data Manager
>  ------------------------------------
> @@ -56,7 +90,7 @@
>      
>  >>> p = P()
>  >>> dm = DM()
> ->>> p._p_oid = oid
> +>>> p._p_oid = "00000012"
>  >>> p._p_jar = dm
>  >>> p._p_changed
>  0
> @@ -127,8 +161,11 @@
>  implementations.
>  
>  >>> p = P()
> ->>> p.__getstate__()
> -{'x': 0}
> +>>> state = p.__getstate__()
> +>>> isinstance(state, dict)
> +True
> +>>> state['x']
> +0
>  >>> p._p_state
>  0
>  
> @@ -255,8 +292,8 @@
>  >>> p = P()
>  >>> p.inc()
>  >>> p.inc()
> ->>> p.__dict__
> -{'x': 2}
> +>>> 'x' in p.__dict__
> +True
>  >>> p._p_jar
>  
>  
> @@ -360,8 +397,8 @@
>  >>> p_shouldHaveDict.__dictoffset__ > 0
>  True
>  >>> x = p_shouldHaveDict()
> ->>> x.__dict__
> -{}
> +>>> isinstance(x.__dict__, dict)
> +True
>  
>  
>  Pickling
> @@ -381,11 +418,31 @@
>  >>> p2.x == p.x
>  True
>  
> -The P2 class has a custom __getstate__ and __setstate__.
> -
> ->>> p = P2()
> ->>> p2 = pickle.loads(pickle.dumps(p))
> ->>> p2.__class__ is P2
> -True
> ->>> p2.__dict__
> -{'v': 42}
> +We should also test that pickle works with custom getstate and
> +setstate.  Perhaps even reduce.  The problem is that pickling depends
> +on finding the class in a particular module, and classes defined here
> +won't appear in any module.  We could require each user of the tests
> +to define a base class, but that might be tedious.
> +
> +Interfaces
> +----------
> +
> +Some versions of Zope and ZODB have the zope.interfaces package
> +available.  If it is available, then persistent will be associated
> +with several interfaces.  It's hard to write a doctest test that runs
> +the tests only if zope.interface is available, so this test looks a
> +little unusual.  One problem is that the assert statements won't do
> +anything if you run with -O.
> +
> +>>> try:
> +...     import zope.interface
> +... except ImportError:
> +...     pass
> +... else:
> +...     from persistent.interfaces import IPersistent
> +...     assert IPersistent.isImplementedByInstancesOf(Persistent)
> +...     p = Persistent()
> +...     assert IPersistent.isImplementedBy(p)
> +...     assert IPersistent.isImplementedByInstancesOf(P)
> +...     p = P()
> +...     assert IPersistent.isImplementedBy(p)
> 
> 
> _______________________________________________
> Zope-Checkins maillist  -  Zope-Checkins at zope.org
> http://mail.zope.org/mailman/listinfo/zope-checkins
> 

-- 
Simplistix - Content Management, Zope & Python Consulting
            - http://www.simplistix.co.uk




More information about the Zope-Checkins mailing list