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

Jeremy Hylton jeremy at zope.com
Wed Mar 3 13:59:43 EST 2004


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)




More information about the Zope-Checkins mailing list