[Zope3-checkins] CVS: Zope3/src/zope/app/process/tests - __init__.py:1.2 test_loggingconfig.py:1.2 test_registerrequestfactory.py:1.2 test_registerservertype.py:1.2 test_requestfactoryregistry.py:1.2 test_schema.py:1.2 test_servertyperegistry.py:1.2 test_simpleregistry.py:1.2

Fred L. Drake, Jr. fred@zope.com
Wed, 25 Jun 2003 11:30:04 -0400


Update of /cvs-repository/Zope3/src/zope/app/process/tests
In directory cvs.zope.org:/tmp/cvs-serv4594/process/tests

Added Files:
	__init__.py test_loggingconfig.py 
	test_registerrequestfactory.py test_registerservertype.py 
	test_requestfactoryregistry.py test_schema.py 
	test_servertyperegistry.py test_simpleregistry.py 
Log Message:
Merged from fdrake-zconfig-in-zope-3-branch:
Replace zope.app.startup with zope.app.process; these contain mostly the same
code, but zope.app.process supports the new startup events instead of calling
various initialization routines directly, and supports configuration of the
appserver using ZConfig.


=== Zope3/src/zope/app/process/tests/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/__init__.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1 @@
+# Make this a package.


=== Zope3/src/zope/app/process/tests/test_loggingconfig.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_loggingconfig.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,223 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""Tests for zLOG configuration via ZConfig."""
+
+import cStringIO as StringIO
+import logging
+import sys
+import tempfile
+import unittest
+
+import ZConfig
+
+
+from zope.app.process import datatypes
+from zope.app.process import loghandlers
+
+
+class TestLoggingConfig(unittest.TestCase):
+
+    # XXX This tries to save and restore the state of logging around
+    # the test.  Somewhat surgical; there may be a better way.
+
+    def setUp(self):
+        self._old_logger = logging.getLogger("event")
+        self._old_level = self._old_logger.level
+        self._old_handlers = self._old_logger.handlers[:]
+        self._old_logger.handlers[:] = [loghandlers.NullHandler()]
+
+    def tearDown(self):
+        for h in self._old_logger.handlers:
+            self._old_logger.removeHandler(h)
+        for h in self._old_handlers:
+            self._old_logger.addHandler(h)
+        self._old_logger.setLevel(self._old_level)
+
+    _schema = None
+    _schematext = """
+      <schema>
+        <import package='zope.app.process'/>
+        <section type='eventlog' name='*' attribute='eventlog'/>
+      </schema>
+    """
+
+    def get_schema(self):
+        if self._schema is None:
+            sio = StringIO.StringIO(self._schematext)
+            self.__class__._schema = ZConfig.loadSchemaFile(sio)
+        return self._schema
+
+    def get_config(self, text):
+        conf, handler = ZConfig.loadConfigFile(self.get_schema(),
+                                               StringIO.StringIO(text))
+        self.assert_(not handler)
+        return conf
+
+    def test_logging_level(self):
+        # Make sure the expected names are supported; it's not clear
+        # how to check the values in a meaningful way.
+        # Just make sure they're case-insensitive.
+        convert = datatypes.logging_level
+        for name in ["notset", "all", "trace", "debug", "blather",
+                     "info", "warn", "warning", "error", "fatal",
+                     "critical"]:
+            self.assertEqual(convert(name), convert(name.upper()))
+        self.assertRaises(ValueError, convert, "hopefully-not-a-valid-value")
+
+    def test_http_method(self):
+        convert = datatypes.get_or_post
+        self.assertEqual(convert("get"), "GET")
+        self.assertEqual(convert("GET"), "GET")
+        self.assertEqual(convert("post"), "POST")
+        self.assertEqual(convert("POST"), "POST")
+        self.assertRaises(ValueError, convert, "")
+        self.assertRaises(ValueError, convert, "foo")
+
+    def test_syslog_facility(self):
+        convert = datatypes.syslog_facility
+        for name in ["auth", "authpriv", "cron", "daemon", "kern",
+                     "lpr", "mail", "news", "security", "syslog",
+                     "user", "uucp", "local0", "local1", "local2",
+                     "local3", "local4", "local5", "local6", "local7"]:
+            self.assertEqual(convert(name), name)
+            self.assertEqual(convert(name.upper()), name)
+        self.assertRaises(ValueError, convert, "hopefully-never-a-valid-value")
+
+    def test_config_without_logger(self):
+        conf = self.get_config("")
+        self.assert_(conf.eventlog is None)
+
+    def test_config_without_handlers(self):
+        logger = self.check_simple_logger("<eventlog/>")
+        # Make sure there's a NullHandler, since a warning gets
+        # printed if there are no handlers:
+        self.assertEqual(len(logger.handlers), 1)
+        self.assert_(isinstance(logger.handlers[0],
+                                loghandlers.NullHandler))
+
+    def test_with_logfile(self):
+        fn = tempfile.mktemp()
+        logger = self.check_simple_logger("<eventlog>\n"
+                                          "  <logfile>\n"
+                                          "    path %s\n"
+                                          "    level debug\n"
+                                          "  </logfile>\n"
+                                          "</eventlog>" % fn)
+        logfile = logger.handlers[0]
+        self.assertEqual(logfile.level, logging.DEBUG)
+        self.assert_(isinstance(logfile, loghandlers.FileHandler))
+
+    def test_with_stderr(self):
+        self.check_standard_stream("stderr")
+
+    def test_with_stdout(self):
+        self.check_standard_stream("stdout")
+
+    def check_standard_stream(self, name):
+        old_stream = getattr(sys, name)
+        conf = self.get_config("""
+            <eventlog>
+              <logfile>
+                level info
+                path %s
+              </logfile>
+            </eventlog>
+            """ % name.upper())
+        self.assert_(conf.eventlog is not None)
+        # The factory has already been created; make sure it picks up
+        # the stderr we set here when we create the logger and
+        # handlers:
+        sio = StringIO.StringIO()
+        setattr(sys, name, sio)
+        try:
+            logger = conf.eventlog()
+        finally:
+            setattr(sys, name, old_stream)
+        logger.warn("woohoo!")
+        self.assert_(sio.getvalue().find("woohoo!") >= 0)
+
+    def test_with_syslog(self):
+        logger = self.check_simple_logger("<eventlog>\n"
+                                          "  <syslog>\n"
+                                          "    level error\n"
+                                          "    facility local3\n"
+                                          "  </syslog>\n"
+                                          "</eventlog>")
+        syslog = logger.handlers[0]
+        self.assertEqual(syslog.level, logging.ERROR)
+        self.assert_(isinstance(syslog, loghandlers.SysLogHandler))
+
+    def test_with_http_logger_localhost(self):
+        logger = self.check_simple_logger("<eventlog>\n"
+                                          "  <http-logger>\n"
+                                          "    level error\n"
+                                          "    method post\n"
+                                          "  </http-logger>\n"
+                                          "</eventlog>")
+        handler = logger.handlers[0]
+        self.assertEqual(handler.host, "localhost")
+        # XXX The "url" attribute of the handler is misnamed; it
+        # really means just the selector portion of the URL.
+        self.assertEqual(handler.url, "/")
+        self.assertEqual(handler.level, logging.ERROR)
+        self.assertEqual(handler.method, "POST")
+        self.assert_(isinstance(handler, loghandlers.HTTPHandler))
+
+    def test_with_http_logger_remote_host(self):
+        logger = self.check_simple_logger("<eventlog>\n"
+                                          "  <http-logger>\n"
+                                          "    method get\n"
+                                          "    url http://example.com/log/\n"
+                                          "  </http-logger>\n"
+                                          "</eventlog>")
+        handler = logger.handlers[0]
+        self.assertEqual(handler.host, "example.com")
+        # XXX The "url" attribute of the handler is misnamed; it
+        # really means just the selector portion of the URL.
+        self.assertEqual(handler.url, "/log/")
+        self.assertEqual(handler.level, logging.NOTSET)
+        self.assertEqual(handler.method, "GET")
+        self.assert_(isinstance(handler, loghandlers.HTTPHandler))
+
+    def test_with_email_notifier(self):
+        logger = self.check_simple_logger("<eventlog>\n"
+                                          "  <email-notifier>\n"
+                                          "    to sysadmin@example.com\n"
+                                          "    to sa-pager@example.com\n"
+                                          "    from zlog-user@example.com\n"
+                                          "    level fatal\n"
+                                          "  </email-notifier>\n"
+                                          "</eventlog>")
+        handler = logger.handlers[0]
+        self.assertEqual(handler.toaddrs, ["sysadmin@example.com",
+                                           "sa-pager@example.com"])
+        self.assertEqual(handler.fromaddr, "zlog-user@example.com")
+        self.assertEqual(handler.level, logging.FATAL)
+
+    def check_simple_logger(self, text, level=logging.INFO):
+        conf = self.get_config(text)
+        self.assert_(conf.eventlog is not None)
+        self.assertEqual(conf.eventlog.level, level)
+        logger = conf.eventlog()
+        self.assert_(isinstance(logger, logging.Logger))
+        self.assertEqual(len(logger.handlers), 1)
+        return logger
+
+
+def test_suite():
+    return unittest.makeSuite(TestLoggingConfig)
+
+if __name__ == '__main__':
+    unittest.main(defaultTest="test_suite")


=== Zope3/src/zope/app/process/tests/test_registerrequestfactory.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_registerrequestfactory.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,97 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+import unittest
+from zope.configuration.xmlconfig import xmlconfig
+from zope.configuration.tests.basetestdirectivesxml import makeconfig
+from zope.app.process.requestfactoryregistry import getRequestFactory
+from zope.testing.cleanup import CleanUp
+from zope.app.interfaces.startup import IPublicationRequestFactoryFactory
+from zope.interface import implements
+
+class TF:
+    "test request factory"
+    implements(IPublicationRequestFactoryFactory)
+
+tf = TF()
+
+class Test(CleanUp, unittest.TestCase):
+
+    def testRegisterRequestFactory(self):
+
+        xmlconfig(makeconfig(
+            '''<directive
+                   name="registerRequestFactory"
+                   attributes="name publication request"
+                   handler=
+                   "zope.app.process.metaconfigure.registerRequestFactory"
+                   />''',
+            '''<test:registerRequestFactory
+                   name="BrowserRequestFactory"
+                   publication=
+             "zope.app.publication.browser.BrowserPublication"
+                   request = "zope.publisher.browser.BrowserRequest" />
+            '''
+            ))
+
+        from zope.app.publication.browser import \
+             BrowserPublication
+        from zope.publisher.browser import BrowserRequest
+
+        self.assertEqual(
+            getRequestFactory('BrowserRequestFactory')._pubFactory,
+            BrowserPublication)
+        self.assertEqual(
+            getRequestFactory('BrowserRequestFactory')._request,
+            BrowserRequest)
+
+
+    def testRegisterRequestFactory_w_factory(self):
+
+        xmlconfig(makeconfig(
+            '''<directive
+                   name="registerRequestFactory"
+                   attributes="name publication request"
+                   handler=
+                   "zope.app.process.metaconfigure.registerRequestFactory"
+                   />''',
+            '''<test:registerRequestFactory
+                   name="BrowserRequestFactory"
+                   factory="
+                   zope.app.process.tests.test_registerrequestfactory.tf"
+                   />
+            '''
+            ))
+
+        import zope.app.process.tests.test_registerrequestfactory
+
+        self.assertEqual(
+            getRequestFactory('BrowserRequestFactory'),
+            zope.app.process.tests.test_registerrequestfactory.tf
+            )
+
+
+
+
+def test_suite():
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


=== Zope3/src/zope/app/process/tests/test_registerservertype.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_registerservertype.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""terServerType.py,v 1.1.2.2 2002/04/02 02:20:40 srichter Exp $
+"""
+
+import unittest
+from zope.configuration.xmlconfig import xmlconfig
+from zope.configuration.tests.basetestdirectivesxml import makeconfig
+from zope.app.process.servertyperegistry import getServerType
+
+
+class Test(unittest.TestCase):
+
+    def testRegisterServerType(self):
+        xmlconfig(makeconfig(
+            '''<directive
+                   name="registerServerType"
+                   attributes="name publication request"
+                   handler="zope.app.process.metaconfigure.registerServerType"
+                   />''',
+            '''<test:registerServerType
+                 name = "Browser"
+                 factory =
+                 "zope.server.http.publisherhttpserver.PublisherHTTPServer"
+                 requestFactory="BrowserRequestFactory"
+                 logFactory =
+                 "zope.server.http.commonhitlogger.CommonHitLogger"
+                 defaultPort="8080"
+                 defaultVerbose="true" />'''
+            ))
+
+        from zope.server.http.publisherhttpserver import PublisherHTTPServer
+        from zope.server.http.commonhitlogger import CommonHitLogger
+
+        self.assertEqual(getServerType('Browser')._factory,
+                         PublisherHTTPServer)
+        self.assertEqual(getServerType('Browser')._logFactory, CommonHitLogger)
+        self.assertEqual(getServerType('Browser')._requestFactory,
+                         "BrowserRequestFactory")
+        self.assertEqual(getServerType('Browser')._defaultPort, 8080)
+        self.assertEqual(getServerType('Browser')._defaultVerbose, 1)
+
+
+
+def test_suite():
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


=== Zope3/src/zope/app/process/tests/test_requestfactoryregistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_requestfactoryregistry.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,51 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+I do not think it is necessary to do the entire SimpleRegistry tests again.
+Instead we will test whether the module in itself works.
+
+$Id$
+"""
+
+import unittest
+from zope.app.process.requestfactoryregistry import \
+     registerRequestFactory, getRequestFactory
+from zope.app.process.requestfactory import IRequestFactory
+from zope.interface import implements
+
+
+class RequestFactory:
+    """RequestFactory Stub."""
+
+    implements(IRequestFactory)
+
+
+class Test(unittest.TestCase):
+
+
+    def testRegistry(self):
+
+        factory = RequestFactory()
+
+        registerRequestFactory('factory', factory)
+        self.assertEqual(getRequestFactory('factory'), factory)
+
+
+def test_suite():
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


=== Zope3/src/zope/app/process/tests/test_schema.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_schema.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test that the Zope appserver configuration schema can be loaded.
+
+$Id$
+"""
+
+import os.path
+import unittest
+
+import ZConfig
+
+
+class TestConfiguration(unittest.TestCase):
+
+    def test_schema(self):
+        dir = os.path.dirname(os.path.dirname(__file__))
+        filename = os.path.join(dir, "schema.xml")
+        ZConfig.loadSchema(filename)
+
+
+def test_suite():
+    return unittest.makeSuite(TestConfiguration)
+
+if __name__ == "__main__":
+    try:
+        __file__
+    except NameError:
+        import sys
+        __file__ = sys.argv[0]
+    unittest.main(defaultTest="test_suite")


=== Zope3/src/zope/app/process/tests/test_servertyperegistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_servertyperegistry.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,51 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+I do not think it is necessary to do the entire SimpleRegistry tests again.
+Instead we will test whether the module in itself works.
+
+$Id$
+"""
+
+import unittest
+from zope.app.process.servertyperegistry import \
+     registerServerType, getServerType
+from zope.app.process.servertype import IServerType
+from zope.interface import implements
+
+
+class ServerType:
+    """ServerType Stub."""
+
+    implements(IServerType)
+
+
+class Test(unittest.TestCase):
+
+
+    def testRegistry(self):
+
+        server = ServerType()
+
+        registerServerType('server', server)
+        self.assertEqual(getServerType('server'), server)
+
+
+def test_suite():
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


=== Zope3/src/zope/app/process/tests/test_simpleregistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Jun 25 11:30:04 2003
+++ Zope3/src/zope/app/process/tests/test_simpleregistry.py	Wed Jun 25 11:29:33 2003
@@ -0,0 +1,99 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+import unittest
+from zope.interface import Interface
+from zope.app.process.simpleregistry import SimpleRegistry, \
+     ZopeDuplicateRegistryEntryError, ZopeIllegalInterfaceError
+from zope.interface import implements
+
+
+class I1(Interface):
+    pass
+
+
+class I2(Interface):
+    pass
+
+
+class Object1:
+    implements(I1)
+
+
+class Object2:
+    implements(I2)
+
+
+class Test(unittest.TestCase):
+
+
+    def testRegister(self):
+
+        registry = SimpleRegistry(I1)
+        obj1 = Object1()
+
+        self.assertEqual(registry.objects, {})
+
+        registry.register('obj1', obj1)
+        self.assertEqual(registry.objects, {'obj1': obj1})
+
+        registry.register('obj2', obj1)
+        self.assertEqual(registry.objects, {'obj1': obj1, 'obj2': obj1})
+
+
+    def testIllegalInterfaceError(self):
+
+        registry = SimpleRegistry(I1)
+        obj2 = Object2()
+
+        self.failUnlessRaises(ZopeIllegalInterfaceError,
+                              registry.register, 'obj2', obj2)
+
+
+    def testDuplicateEntry(self):
+
+        registry = SimpleRegistry(I1)
+        obj1 = Object1()
+        registry.register('obj1', obj1)
+
+        self.failUnlessRaises(ZopeDuplicateRegistryEntryError,
+                              registry.register, 'obj1', obj1)
+
+
+    def testGet(self):
+
+        registry = SimpleRegistry(I1)
+        obj1 = Object1()
+        obj2 = Object1()
+        registry.objects = {'obj1': obj1, 'obj2': obj2}
+
+        self.assertEqual(registry.get('obj1'), obj1)
+        self.assertEqual(registry.get('obj2'), obj2)
+
+        # Requesting an object that does not exist
+        self.assertEqual(registry.get('obj3'), None)
+
+
+
+def test_suite():
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())