zope.app.testing-3.10.0/0000755000175000017500000000000011704136013013117 5ustar jimjimzope.app.testing-3.10.0/.bzrignore0000644000175000017500000000010011704135707015121 0ustar jimjim./.installed.cfg ./bin ./develop-eggs ./eggs ./parts *.egg-info zope.app.testing-3.10.0/bootstrap.py0000644000175000017500000000337311704135707015525 0ustar jimjim############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. $Id: bootstrap.py 110724 2010-04-11 00:04:11Z tseaver $ """ import os, shutil, sys, tempfile, urllib2 tmpeggs = tempfile.mkdtemp() ez = {} exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) import pkg_resources cmd = 'from setuptools.command.easy_install import main; main()' if sys.platform == 'win32': cmd = '"%s"' % cmd # work around spawn lamosity on windows ws = pkg_resources.working_set assert os.spawnle( os.P_WAIT, sys.executable, sys.executable, '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout', dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse('setuptools')).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout') import zc.buildout.buildout zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) shutil.rmtree(tmpeggs) zope.app.testing-3.10.0/setup.py0000644000175000017500000000676411704135763014661 0ustar jimjim############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.app.testing package $Id: setup.py 124042 2012-01-13 23:19:15Z jim $ """ import os from setuptools import setup, find_packages def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() setup(name='zope.app.testing', version = '3.10.0', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Zope Application Testing Support', long_description=( read('README.txt') + '\n\n.. contents::\n\n' + read('src', 'zope', 'app', 'testing', 'dochttp.txt') + '\n\n' + read('src', 'zope', 'app', 'testing', 'doctest.txt') + '\n\n' + read('CHANGES.txt') ), keywords = "zope3 test testing setup functional", classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.app.testing', license='ZPL 2.1', packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope', 'zope.app'], extras_require=dict(test=[ 'ZODB3', 'zope.app.zcmlfiles', 'zope.login', 'zope.publisher >= 3.12', 'zope.securitypolicy', ]), install_requires=['setuptools', 'zope.annotation', 'zope.app.appsetup >= 3.11', 'zope.processlifetime', 'zope.app.debug', 'zope.app.dependable', 'zope.app.publication', # We need zope.component with the hooks module. 'zope.component >= 3.8', 'zope.container', 'zope.i18n', 'zope.interface', 'zope.password', 'zope.publisher', 'zope.schema', 'zope.security', 'zope.site', 'zope.testing', 'zope.testbrowser >= 4', 'zope.traversing', ], include_package_data = True, zip_safe = False, ) zope.app.testing-3.10.0/PKG-INFO0000644000175000017500000003321511704136013014220 0ustar jimjimMetadata-Version: 1.0 Name: zope.app.testing Version: 3.10.0 Summary: Zope Application Testing Support Home-page: http://pypi.python.org/pypi/zope.app.testing Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: This package provides testing support for Zope 3 applications. Besides providing numerous setup convenience functions, it implements a testing setup that allows the user to make calls to the publisher allowing to write functional tests. .. contents:: ================= FDocTest (How-To) ================= Steps to get started: 1. Use a clean/missing Data.fs 2. Create a manager with the name "mgr", password "mgrpw", and grant the zope.Manager role. 3. Install tcpwatch. 4. Create a temporary directory to record tcpwatch output. 5. Run tcpwatch using: tcpwatch.py -L 8081:8080 -s -r tmpdir (the ports are the listening port and forwarded-to port; the second need to match the Zope configuration) 6. In a browser, connect to the listening port and do whatever needs to be recorded. 7. Shut down tcpwatch. 8. Run the script src/zope/app/testing/dochttp.py: python2.4 src/zope/app/testing/dochttp.py tmpdir > somefile.txt 9. Edit the generated text file to add explanations and elide uninteresting portions of the output. 10. In a functional test module (usually ftests.py), import FunctionalDocFileSuite from zope.app.testing.functional and instantiate it, passing the name of the text file containing the test. ======================== DocTest Functional Tests ======================== This file documents and tests doctest-based functional tests and basic Zope web-application functionality. Request/Response Functional Tests --------------------------------- You can create Functional tests as doctests. Typically, this is done by using a script such as src/zope/app/testing/dochttp.py to convert tcpwatch recorded output to a doctest, which is then edited to provide explanation and to remove uninteresting details. That is how this file was created. Here we'll test some of the most basic types of access. First, we'll test accessing a protected page without credentials: >>> print http(r""" ... GET /@@contents.html HTTP/1.1 ... """) HTTP/1.1 401 Unauthorized Cache-Control: no-store, no-cache, must-revalidate Content-Length: ... Content-Type: text/html;charset=utf-8 Expires: Mon, 26 Jul 1997 05:00:00 GMT Pragma: no-cache WWW-Authenticate: basic realm="Zope" >> print http(r""" ... GET /@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> print http(r""" ... GET /++etc++site/@@manage HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.1 303 See Other Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@contents.html Note that, in this case, we got a 303 response. A 303 response is the prefered response for this sort of redirect with HTTP 1.1. If we used HTTP 1.0, we'd get a 302 response: >>> print http(r""" ... GET /++etc++site/@@manage HTTP/1.0 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.0 302 Moved Temporarily Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@contents.html Lets visit the page we were redirected to: >>> print http(r""" ... GET /++etc++site/@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> print http(r""" ... GET / HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> root = getRootFolder() >>> root You can intermix HTTP requests with regular Python calls. Note, however, that making an `http()` call implied a transaction commit. If you want to throw away changes made in Python code, abort the transaction before the HTTP request. >>> print http(r""" ... POST /@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Content-Length: 73 ... Content-Type: application/x-www-form-urlencoded ... ... type_name=BrowserAdd__zope.site.folder.Folder&new_value=f1""", ... handle_errors=False) HTTP/1.1 303 See Other Content-Length: ... Content-Type: text/html;charset=utf-8 Location: http://localhost/@@contents.html >> list(root.keys()) [u'f1'] ======= CHANGES ======= 3.10.0 (2012-01-13) ------------------- - Removed test dependency on ``zope.app.authentication``. zope.testbrowser 4 depends on this change (seriously) if it find zope.app.testing. 3.9.0 (2011-03-14) ------------------ - Move zope.app.testing testbrowser functionality into zope.app.testing. This requires zope.testbrowser version 4.0.0 or above. 3.8.1 (2011-01-07) ------------------ - Include REMOTE_ADDR ('127.0.0.1') in the request environment. 3.8.0 (2010-09-14) ------------------ - Remove invalid HTTP_REFERER default. (We both don't want a default to allow others testing without a referer and 'localhost' is not a reasonable default anyway.) This improves the situation for #98437 - Made the xmlrpc code compatible with Python 2.7. - Removed test dependency on ``zope.app.zptpage``. - Switched test dependency from ``zope.app.securitypolicy`` to ``zope.securitypolicy``. 3.7.7 (2010-09-14) ------------------ - Rereleasing 3.7.5 as 3.7.7 to fix brown bag release. 3.7.6 (2010-09-14) ------------------ - Brown bag release: It broke the tests of ``zope.testbrowser``. 3.7.5 (2010-04-10) ------------------ - Switch doctests to use the stdlib ``doctest`` module, rather than the deprecated ``zope.testing.doctest`` variant. 3.7.4 (2010-01-08) ------------------ - Import hooks functionality from zope.component after it was moved there from zope.site. - Import ISite from zope.component after it was moved there from zope.location. This lifts the dependency on zope.location. - Fix tests using a newer zope.publisher that requires zope.login. 3.7.3 (2009-08-20) ------------------ - Fixed tests for python 2.4 as well as python 2.5 and 2.6; the change in version 3.7.1 introduced test regressions in python 2.4. 3.7.2 (2009-07-24) ------------------ - Adjusted tests after the referenced memory leak problem has been fixed in ``zope.component``. 3.7.1 (2009-07-21) ------------------ - Fixed failing tests. The code revealed that the tests expected the wrong value. 3.7.0 (2009-06-19) ------------------ - Depend on new ``zope.processlifetime`` interfaces instead of using BBB imports from ``zope.app.appsetup``. - Removed unused dependency on ``zope.app.component``. 3.6.2 (2009-04-26) ------------------ - Removed deprecated back35 module and loose the dependency on ``zope.deferredimport``. - Adapt to ``zope.app.authentication`` refactoring. We depend on ``zope.password`` now instead. - Adapt to latest ``zope.app.security`` refactoring. We don't need this package anymore. 3.6.1 (2009-03-12) ------------------ - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition for calling setDefaultSkin in HTTPCaller. This at the same time removes dependency to the browser part of zope.publisher. - Adapt to the move of IDefaultViewName from zope.component.interfaces to zope.publisher.interfaces. - Remove the DEPENDENCIES.cfg file for zpkg. 3.6.0 (2009-02-01) ------------------ - Fix AttributeError in ``zope.app.testing.setup.setUpTestAsModule`` (when called without name argument). - Use ``zope.container`` instead of ``zope.app.container``. - Use ``zope.site`` instead of ``zope.app.folder`` and ``zope.app.component`` for some parts. 3.5.6 (2008-10-13) ------------------ - Change argument variable name in provideAdapter to not conflict with buitin keyword in Python 2.6. 3.5.5 (2008-10-10) ------------------ - Re-configured functional test setup to create test-specific instances of HTTPCaller to ensure that cookies are not shared by doctests in a test suite. 3.5.4 (2008-08-25) ------------------ - Clean up some transaction management in the functional test setup. 3.5.3 (2008-08-22) ------------------ - Fix isolation enforcement for product configuration around individual tests. 3.5.2 (2008-08-21) ------------------ - Added missing dependency information in setup.py. - Added missing import. - Repair memory leak fix released in 3.4.3 to be more sane in the presence of generations. 3.5.1 (2008-08-20) ------------------ - Correct Fred's "I'm a doofus" release. 3.5.0 (2008-08-20) ------------------ - Add support for product-configuration as part of functional layers; this more closely mirrors the configuration order for normal operation. 3.4.3 (2008-07-25) ------------------ - Fix memory leak in all functional tests. see: https://bugs.launchpad.net/zope3/+bug/251273 3.4.2 (2008-02-02) ------------------ - Fix of 599 error on conflict error in request see: http://mail.zope.org/pipermail/zope-dev/2008-January/030844.html 3.4.1 (2007-10-31) ------------------ - Fixed deprecation warning for ``ZopeSecurityPolicy``. 3.4.0 (2007-10-27) ------------------ - Initial release independent of the main Zope tree. Keywords: zope3 test testing setup functional Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.app.testing-3.10.0/LICENSE.txt0000644000175000017500000000402611704135707014755 0ustar jimjimZope Public License (ZPL) Version 2.1 A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zope.app.testing-3.10.0/CHANGES.txt0000644000175000017500000001131411704135707014741 0ustar jimjim======= CHANGES ======= 3.10.0 (2012-01-13) ------------------- - Removed test dependency on ``zope.app.authentication``. zope.testbrowser 4 depends on this change (seriously) if it find zope.app.testing. 3.9.0 (2011-03-14) ------------------ - Move zope.app.testing testbrowser functionality into zope.app.testing. This requires zope.testbrowser version 4.0.0 or above. 3.8.1 (2011-01-07) ------------------ - Include REMOTE_ADDR ('127.0.0.1') in the request environment. 3.8.0 (2010-09-14) ------------------ - Remove invalid HTTP_REFERER default. (We both don't want a default to allow others testing without a referer and 'localhost' is not a reasonable default anyway.) This improves the situation for #98437 - Made the xmlrpc code compatible with Python 2.7. - Removed test dependency on ``zope.app.zptpage``. - Switched test dependency from ``zope.app.securitypolicy`` to ``zope.securitypolicy``. 3.7.7 (2010-09-14) ------------------ - Rereleasing 3.7.5 as 3.7.7 to fix brown bag release. 3.7.6 (2010-09-14) ------------------ - Brown bag release: It broke the tests of ``zope.testbrowser``. 3.7.5 (2010-04-10) ------------------ - Switch doctests to use the stdlib ``doctest`` module, rather than the deprecated ``zope.testing.doctest`` variant. 3.7.4 (2010-01-08) ------------------ - Import hooks functionality from zope.component after it was moved there from zope.site. - Import ISite from zope.component after it was moved there from zope.location. This lifts the dependency on zope.location. - Fix tests using a newer zope.publisher that requires zope.login. 3.7.3 (2009-08-20) ------------------ - Fixed tests for python 2.4 as well as python 2.5 and 2.6; the change in version 3.7.1 introduced test regressions in python 2.4. 3.7.2 (2009-07-24) ------------------ - Adjusted tests after the referenced memory leak problem has been fixed in ``zope.component``. 3.7.1 (2009-07-21) ------------------ - Fixed failing tests. The code revealed that the tests expected the wrong value. 3.7.0 (2009-06-19) ------------------ - Depend on new ``zope.processlifetime`` interfaces instead of using BBB imports from ``zope.app.appsetup``. - Removed unused dependency on ``zope.app.component``. 3.6.2 (2009-04-26) ------------------ - Removed deprecated back35 module and loose the dependency on ``zope.deferredimport``. - Adapt to ``zope.app.authentication`` refactoring. We depend on ``zope.password`` now instead. - Adapt to latest ``zope.app.security`` refactoring. We don't need this package anymore. 3.6.1 (2009-03-12) ------------------ - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition for calling setDefaultSkin in HTTPCaller. This at the same time removes dependency to the browser part of zope.publisher. - Adapt to the move of IDefaultViewName from zope.component.interfaces to zope.publisher.interfaces. - Remove the DEPENDENCIES.cfg file for zpkg. 3.6.0 (2009-02-01) ------------------ - Fix AttributeError in ``zope.app.testing.setup.setUpTestAsModule`` (when called without name argument). - Use ``zope.container`` instead of ``zope.app.container``. - Use ``zope.site`` instead of ``zope.app.folder`` and ``zope.app.component`` for some parts. 3.5.6 (2008-10-13) ------------------ - Change argument variable name in provideAdapter to not conflict with buitin keyword in Python 2.6. 3.5.5 (2008-10-10) ------------------ - Re-configured functional test setup to create test-specific instances of HTTPCaller to ensure that cookies are not shared by doctests in a test suite. 3.5.4 (2008-08-25) ------------------ - Clean up some transaction management in the functional test setup. 3.5.3 (2008-08-22) ------------------ - Fix isolation enforcement for product configuration around individual tests. 3.5.2 (2008-08-21) ------------------ - Added missing dependency information in setup.py. - Added missing import. - Repair memory leak fix released in 3.4.3 to be more sane in the presence of generations. 3.5.1 (2008-08-20) ------------------ - Correct Fred's "I'm a doofus" release. 3.5.0 (2008-08-20) ------------------ - Add support for product-configuration as part of functional layers; this more closely mirrors the configuration order for normal operation. 3.4.3 (2008-07-25) ------------------ - Fix memory leak in all functional tests. see: https://bugs.launchpad.net/zope3/+bug/251273 3.4.2 (2008-02-02) ------------------ - Fix of 599 error on conflict error in request see: http://mail.zope.org/pipermail/zope-dev/2008-January/030844.html 3.4.1 (2007-10-31) ------------------ - Fixed deprecation warning for ``ZopeSecurityPolicy``. 3.4.0 (2007-10-27) ------------------ - Initial release independent of the main Zope tree. zope.app.testing-3.10.0/README.txt0000644000175000017500000000035511704135707014631 0ustar jimjimThis package provides testing support for Zope 3 applications. Besides providing numerous setup convenience functions, it implements a testing setup that allows the user to make calls to the publisher allowing to write functional tests. zope.app.testing-3.10.0/setup.cfg0000644000175000017500000000007311704136013014740 0ustar jimjim[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.app.testing-3.10.0/src/0000755000175000017500000000000011704136013013706 5ustar jimjimzope.app.testing-3.10.0/src/zope/0000755000175000017500000000000011704136013014663 5ustar jimjimzope.app.testing-3.10.0/src/zope/__init__.py0000644000175000017500000000031011704135707016777 0ustar jimjim# this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) zope.app.testing-3.10.0/src/zope/app/0000755000175000017500000000000011704136013015443 5ustar jimjimzope.app.testing-3.10.0/src/zope/app/__init__.py0000644000175000017500000000031011704135707017557 0ustar jimjim# this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) zope.app.testing-3.10.0/src/zope/app/testing/0000755000175000017500000000000011704136013017120 5ustar jimjimzope.app.testing-3.10.0/src/zope/app/testing/ftesting.zcml0000644000175000017500000000250211704135707021642 0ustar jimjim zope.app.testing-3.10.0/src/zope/app/testing/__init__.py0000644000175000017500000000004311704135707021237 0ustar jimjim# Make directory a Python package. zope.app.testing-3.10.0/src/zope/app/testing/doctest.txt0000644000175000017500000000765211704135707021351 0ustar jimjim======================== DocTest Functional Tests ======================== This file documents and tests doctest-based functional tests and basic Zope web-application functionality. Request/Response Functional Tests --------------------------------- You can create Functional tests as doctests. Typically, this is done by using a script such as src/zope/app/testing/dochttp.py to convert tcpwatch recorded output to a doctest, which is then edited to provide explanation and to remove uninteresting details. That is how this file was created. Here we'll test some of the most basic types of access. First, we'll test accessing a protected page without credentials: >>> print http(r""" ... GET /@@contents.html HTTP/1.1 ... """) HTTP/1.1 401 Unauthorized Cache-Control: no-store, no-cache, must-revalidate Content-Length: ... Content-Type: text/html;charset=utf-8 Expires: Mon, 26 Jul 1997 05:00:00 GMT Pragma: no-cache WWW-Authenticate: basic realm="Zope" >> print http(r""" ... GET /@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> print http(r""" ... GET /++etc++site/@@manage HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.1 303 See Other Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@contents.html Note that, in this case, we got a 303 response. A 303 response is the prefered response for this sort of redirect with HTTP 1.1. If we used HTTP 1.0, we'd get a 302 response: >>> print http(r""" ... GET /++etc++site/@@manage HTTP/1.0 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.0 302 Moved Temporarily Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@contents.html Lets visit the page we were redirected to: >>> print http(r""" ... GET /++etc++site/@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> print http(r""" ... GET / HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> root = getRootFolder() >>> root You can intermix HTTP requests with regular Python calls. Note, however, that making an `http()` call implied a transaction commit. If you want to throw away changes made in Python code, abort the transaction before the HTTP request. >>> print http(r""" ... POST /@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Content-Length: 73 ... Content-Type: application/x-www-form-urlencoded ... ... type_name=BrowserAdd__zope.site.folder.Folder&new_value=f1""", ... handle_errors=False) HTTP/1.1 303 See Other Content-Length: ... Content-Type: text/html;charset=utf-8 Location: http://localhost/@@contents.html >> list(root.keys()) [u'f1'] zope.app.testing-3.10.0/src/zope/app/testing/xmlrpc.py0000644000175000017500000000535611704135707021021 0ustar jimjim############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """XMLRPC testing helpers for Zope 3. $Id: xmlrpc.py 116141 2010-09-02 15:05:04Z patricks $ """ import httplib import StringIO import xmlrpclib from zope.app.testing.functional import HTTPCaller class FakeSocket(object): def __init__(self, data): self.data = data def makefile(self, mode, bufsize=None): return StringIO.StringIO(self.data) class ZopeTestTransport(xmlrpclib.Transport): """xmlrpclib transport that delegates to zope.app.testing.functional.HTTPCaller. It can be used like a normal transport, including support for basic authentication. """ verbose = False handleErrors = True def request(self, host, handler, request_body, verbose=0): request = "POST %s HTTP/1.0\n" % (handler,) request += "Content-Length: %i\n" % len(request_body) request += "Content-Type: text/xml\n" host, extra_headers, x509 = self.get_host_info(host) if extra_headers: request += "Authorization: %s\n" % ( dict(extra_headers)["Authorization"],) request += "\n" + request_body response = HTTPCaller()(request, handle_errors=self.handleErrors) errcode = response.getStatus() errmsg = response.getStatusString() # This is not the same way that the normal transport deals with the # headers. headers = response.getHeaders() if errcode != 200: raise xmlrpclib.ProtocolError( host + handler, errcode, errmsg, headers ) res = httplib.HTTPResponse(FakeSocket(response.getBody())) res.begin() return self.parse_response(res) def ServerProxy(uri, transport=None, encoding=None, verbose=0, allow_none=0, handleErrors=True): """A factory that creates a server proxy using the ZopeTestTransport by default. """ if transport is None: transport = ZopeTestTransport() if isinstance(transport, ZopeTestTransport): transport.handleErrors = handleErrors return xmlrpclib.ServerProxy(uri, transport, encoding, verbose, allow_none) zope.app.testing-3.10.0/src/zope/app/testing/cookieTestOne.txt0000644000175000017500000000423411704135707022450 0ustar jimjim======================== DocTest Functional Tests ======================== This file documents and tests doctest-based functional tests and basic Zope web-application functionality. This second DocTest, zope/app/testing/cookieTestOne.txt, has specifically been created in order to make sure cookie information is not being saved across a test suite. If we are saving these via a global 'http' instance, we will see more results than those listed below. 'http' is instead created in setUp within _prepare_doctest_keywords, rather than in the global declarations. Now we will run tests to ensure that cookies are not saved across doctests. >>> from zope.app.testing import functional >>> from zope.app.testing.tests import DummyCookiesResponse We will create some cookie values and saved them in our 'http' value, which is a CookieHandler() object. >>> response = DummyCookiesResponse(dict( ... proton=dict(value='fromCookieTestOne', ... path='/foo', ... comment='rest is ignored'), ... neutron=dict(value='fromCookieTestOne'))) If 'http' is created as a global variable, then every doctest in this suite will be saving cookies in it, and one doctest may see cookies for another doctest. We only want two cookies in 'http' - the ones we just created. >>> http.saveCookies(response) >>> len(http.cookies) 2 >>> http.cookies['proton'].OutputString() 'proton=fromCookieTestOne; Path=/foo...' >>> http.cookies >>> http.cookies['proton'] = 'fromCookieTestOne' >>> http.cookies['proton']['path'] = '/foo' >>> http.cookies['electron'] = 'fromCookieTestOne' >>> http.cookies['electron']['path'] = '/foo/baz' >>> http.cookies['neutron'] = 'fromCookieTestOne' >>> cookieHeader = http.httpCookie('/foo/bar') >>> parts = cookieHeader.split('; ') >>> parts.sort() >>> parts ['neutron=fromCookieTestOne', 'proton=fromCookieTestOne'] >>> cookieHeader = http.httpCookie('/foo/baz') >>> parts = cookieHeader.split('; ') >>> parts.sort() >>> parts ['electron=fromCookieTestOne', 'neutron=fromCookieTestOne', 'proton=fromCookieTestOne'] zope.app.testing-3.10.0/src/zope/app/testing/setup.py0000644000175000017500000001505111704135707020645 0ustar jimjim############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """Setting up an environment for testing context-dependent objects $Id: setup.py 110724 2010-04-11 00:04:11Z tseaver $ """ import zope.component import zope.traversing.api #------------------------------------------------------------------------ # Annotations from zope.annotation.attribute import AttributeAnnotations def setUpAnnotations(): zope.component.provideAdapter(AttributeAnnotations) #------------------------------------------------------------------------ # Dependencies from zope.annotation.interfaces import IAttributeAnnotatable from zope.app.dependable import Dependable from zope.app.dependable.interfaces import IDependable def setUpDependable(): zope.component.provideAdapter(Dependable, (IAttributeAnnotatable,), IDependable) #------------------------------------------------------------------------ # Traversal from zope.traversing.interfaces import ITraversable from zope.container.interfaces import ISimpleReadContainer from zope.container.traversal import ContainerTraversable def setUpTraversal(): from zope.traversing.testing import setUp setUp() zope.component.provideAdapter(ContainerTraversable, (ISimpleReadContainer,), ITraversable) #------------------------------------------------------------------------ # ISiteManager lookup from zope.site.site import SiteManagerAdapter from zope.component.interfaces import IComponentLookup from zope.interface import Interface def setUpSiteManagerLookup(): zope.component.provideAdapter(SiteManagerAdapter, (Interface,), IComponentLookup) #------------------------------------------------------------------------ # Placeful setup import zope.component.hooks from zope.app.testing.placelesssetup import setUp as placelessSetUp from zope.app.testing.placelesssetup import tearDown as placelessTearDown def placefulSetUp(site=False): placelessSetUp() zope.component.hooks.setHooks() setUpAnnotations() setUpDependable() setUpTraversal() setUpSiteManagerLookup() if site: site = rootFolder() createSiteManager(site, setsite=True) return site def placefulTearDown(): placelessTearDown() zope.component.hooks.resetHooks() zope.component.hooks.setSite() #------------------------------------------------------------------------ # Sample Folder Creation from zope.site.folder import Folder, rootFolder def buildSampleFolderTree(): # set up a reasonably complex folder structure # # ____________ rootFolder ______________________________ # / \ \ # folder1 __________________ folder2 folder3 # | \ | | # folder1_1 ____ folder1_2 folder2_1 folder3_1 # | \ | | # folder1_1_1 folder1_1_2 folder1_2_1 folder2_1_1 root = rootFolder() root[u'folder1'] = Folder() root[u'folder1'][u'folder1_1'] = Folder() root[u'folder1'][u'folder1_1'][u'folder1_1_1'] = Folder() root[u'folder1'][u'folder1_1'][u'folder1_1_2'] = Folder() root[u'folder1'][u'folder1_2'] = Folder() root[u'folder1'][u'folder1_2'][u'folder1_2_1'] = Folder() root[u'folder2'] = Folder() root[u'folder2'][u'folder2_1'] = Folder() root[u'folder2'][u'folder2_1'][u'folder2_1_1'] = Folder() root[u"\N{CYRILLIC SMALL LETTER PE}" u"\N{CYRILLIC SMALL LETTER A}" u"\N{CYRILLIC SMALL LETTER PE}" u"\N{CYRILLIC SMALL LETTER KA}" u"\N{CYRILLIC SMALL LETTER A}3"] = Folder() root[u"\N{CYRILLIC SMALL LETTER PE}" u"\N{CYRILLIC SMALL LETTER A}" u"\N{CYRILLIC SMALL LETTER PE}" u"\N{CYRILLIC SMALL LETTER KA}" u"\N{CYRILLIC SMALL LETTER A}3"][ u"\N{CYRILLIC SMALL LETTER PE}" u"\N{CYRILLIC SMALL LETTER A}" u"\N{CYRILLIC SMALL LETTER PE}" u"\N{CYRILLIC SMALL LETTER KA}" u"\N{CYRILLIC SMALL LETTER A}3_1"] = Folder() return root #------------------------------------------------------------------------ # Sample Folder Creation from zope.site.site import LocalSiteManager import zope.component.interfaces def createSiteManager(folder, setsite=False): if not zope.component.interfaces.ISite.providedBy(folder): folder.setSiteManager(LocalSiteManager(folder)) if setsite: zope.component.hooks.setSite(folder) return zope.traversing.api.traverse(folder, "++etc++site") #------------------------------------------------------------------------ # Local Utility Addition def addUtility(sitemanager, name, iface, utility, suffix=''): """Add a utility to a site manager This helper function is useful for tests that need to set up utilities. """ folder_name = (name or (iface.__name__ + 'Utility')) + suffix default = sitemanager['default'] default[folder_name] = utility utility = default[folder_name] sitemanager.registerUtility(utility, iface, name) return utility #------------------------------------------------------------------------ # Setup of test text files as modules import sys # Evil hack to make pickling work with classes defined in doc tests class NoCopyDict(dict): def copy(self): return self class FakeModule: """A fake module.""" def __init__(self, dict): self.__dict = dict def __getattr__(self, name): try: return self.__dict[name] except KeyError: raise AttributeError(name) def setUpTestAsModule(test, name=None): if name is None: if test.globs.has_key('__name__'): name = test.globs['__name__'] else: name = test.globs.name test.globs['__name__'] = name test.globs = NoCopyDict(test.globs) sys.modules[name] = FakeModule(test.globs) def tearDownTestAsModule(test): del sys.modules[test.globs['__name__']] test.globs.clear() zope.app.testing-3.10.0/src/zope/app/testing/dochttp.py0000644000175000017500000001650411704135707021156 0ustar jimjim############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """Convert an http tcpwatch session to a doctest $Id: dochttp.py 123984 2012-01-07 17:43:12Z menesis $ """ import errno import optparse import os import re import rfc822 import sys usage = """usage: %prog directory Convert an http tcpwatch recorded sesssion to a doctest file, which is written to standard output. """ parser = optparse.OptionParser(usage) parser.add_option("-p", "--prefix", default="watch", help="Prefix for recorded tcpwatch session files") parser.add_option("-U", "--skip-url", action="append", help="Regular expression for URLs to skip") parser.add_option("-E", "--skip-extension", action="append", help="URL file-extension to skip") parser.add_option("-e", "--extension", action="append", help="URL file-extension to include") parser.add_option("-I", "--skip-request-header", action="append", help="Request header to skip") parser.add_option("-O", "--skip-response-header", action="append", help="Response header to skip") parser.add_option("-r", "--clean-redirects", action="store_true", help="Strip content from redirect responses", default=False) default_options = [ '-e', 'html', '-I', 'Accept-Charset', '-I', 'Accept-Encoding', '-I', 'Accept-Language', '-I', 'Accept', '-I', 'Connection', '-I', 'Host', '-I', 'Keep-Alive', '-I', 'User-Agent', '-O', 'Date', '-O', 'Server', '-O', 'X-Content-Type-Warning', '-O', 'X-Powered-By', ] def dochttp(args=sys.argv[1:], default=None): """Convert a tcpwatch recorded sesssion to a doctest file""" if default is None: default = default_options options, args = parser.parse_args(default+args) try: directory, = args except: parser.print_help() sys.exit(1) skip_extensions = options.skip_extension or () extensions = [ext for ext in (options.extension or ()) if ext not in skip_extensions] skip_urls = [re.compile(pattern) for pattern in (options.skip_url or ())] names = [name[:-len(".request")] for name in os.listdir(directory) if name.startswith(options.prefix) and name.endswith('.request') ] names.sort() extre = re.compile("[.](\w+)$") for name in names: requests = Requests( open(os.path.join(directory, name + ".request"), 'rb'), options.skip_request_header, ) responses = Responses( open(os.path.join(directory, name + ".response"), 'rb'), options.skip_response_header, ) # We use map so as *not* to truncate at shortest input. # We want an error if the number of requests and responses # is different. for request, response in map(None, requests, responses): assert (request and response) or not (request or response) path = request.path ext = extre.search(path) if ext: ext = ext.group(1) if extensions: if ext not in extensions: continue else: if ext in skip_extensions: continue for skip_url in skip_urls: if skip_url.search(request.path): break else: try: output_test(request, response, options.clean_redirects) except IOError, e: if e.errno == errno.EPIPE: return raise def output_test(request, response, clean_redirects=False): print print print ' >>> print http(r"""' print ' ...', '\n ... '.join(request.lines())+'""")' if response.code in (301, 302, 303) and clean_redirects: content_length = None if response.headers: for i in range(len(response.headers)): h, v = response.headers[i] if h == "Content-Length": content_length = int(v) response.headers[i] = (h, "...") lines = response.header_lines() if lines and content_length == 0: lines.append("...") else: lines = response.lines() print ' ', '\n '.join([line.rstrip() and line or '' for line in lines]) class Message: start = '' def __init__(self, file, skip_headers): start = file.readline().rstrip() if start: self.start = start if start.startswith("HTTP/"): # This is a response; extract the response code: self.code = int(start.split()[1]) headers = [split_header(header) for header in rfc822.Message(file).headers ] headers = [ ('-'.join([s.capitalize() for s in name.split('-')]), v.rstrip() ) for (name, v) in headers if name.lower() not in skip_headers ] self.headers = headers content_length = int(dict(headers).get('Content-Length', '0')) if content_length: self.body = file.read(content_length).split('\n') else: self.body = [] def __nonzero__(self): return bool(self.start) def lines(self): output = self.header_lines() if output: output.extend(self.body) return output def header_lines(self): if self.start: output = [self.start] headers = ["%s: %s" % (name, v) for (name, v) in self.headers] headers.sort() output.extend(headers) output.append('') else: output = [] return output headerre = re.compile('(\S+): (.+)$') def split_header(header): return headerre.match(header).group(1, 2) def messages(cls, file, skip_headers): skip_headers = [name.lower() for name in (skip_headers or ())] while 1: message = cls(file, skip_headers) if message: yield message else: break class Request(Message): path = '' def __init__(self, file, skip_headers): Message.__init__(self, file, skip_headers) if self.start: self.command, self.path, self.protocol = self.start.split() def Requests(file, skip_headers): return messages(Request, file, skip_headers) def Responses(file, skip_headers): return messages(Message, file, skip_headers) main = dochttp if __name__ == '__main__': main() zope.app.testing-3.10.0/src/zope/app/testing/functional.py0000644000175000017500000007126111704135707021654 0ustar jimjim############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """Functional testing framework for Zope 3. There should be a file 'ftesting.zcml' in the current directory. $Id: functional.py 119446 2011-01-07 19:50:06Z mgedmin $ """ import copy import doctest import logging import os.path import re import rfc822 import sys import traceback import unittest from StringIO import StringIO from Cookie import SimpleCookie from transaction import abort, commit from ZODB.DB import DB from ZODB.DemoStorage import DemoStorage from ZODB.interfaces import IDatabase from zope import component from zope.publisher.interfaces import ISkinnable from zope.publisher.browser import BrowserRequest from zope.publisher.http import HTTPRequest from zope.publisher.publish import publish from zope.publisher.skinnable import setDefaultSkin from zope.security.interfaces import Forbidden, Unauthorized import zope.app.appsetup.product import zope.app.testing.setup from zope.app.appsetup.appsetup import multi_database from zope.app.debug import Debugger from zope.app.publication.http import HTTPPublication from zope.app.publication.zopepublication import ZopePublication from zope.app.publication.httpfactory import chooseClasses from zope.component.hooks import setSite, getSite class ResponseWrapper(object): """A wrapper that adds several introspective methods to a response.""" def __init__(self, response, path, request, omit=()): self._response = response self._path = path self._request = request self.omit = omit self._body = None def getOutput(self): """Returns the full HTTP output (headers + body)""" body = self.getBody() omit = self.omit headers = [x for x in self._response.getHeaders() if x[0].lower() not in omit] headers.sort() headers = '\n'.join([("%s: %s" % (n, v)) for (n, v) in headers]) statusline = '%s %s' % (self._response._request['SERVER_PROTOCOL'], self._response.getStatusString()) if body: return '%s\n%s\n\n%s' % (statusline, headers, body) else: return '%s\n%s\n' % (statusline, headers) def getBody(self): """Returns the response body""" if self._body is None: self._body = ''.join(self._response.consumeBody()) return self._body def getPath(self): """Returns the path of the request""" return self._path def __getattr__(self, attr): return getattr(self._response, attr) __str__ = getOutput class IManagerSetup(zope.interface.Interface): """Utility for enabling up a functional testing manager with needed grants TODO This is an interim solution. It tries to break the dependence on a particular security policy, however, we need a much better way of managing functional-testing configurations. """ def setUpManager(): """Set up the manager, zope.mgr """ class BaseDatabaseFactory(object): """Factory object for passing to appsetup.multi_databases This class is an internal implementation detail, subject to change without notice! It is currently used by FunctionalTestSetUp.__init__ to create the basic storage(s) containing the data that is common to all tests in a layer. The constructor takes the name of the new database, and a dictionary of storages. The 'open' method creates a new DemoStorage, and adds it to the storage dictionary under the given name. Then creates and returns a named DB object using the storage. """ def __init__(self, name, base_storages): self.name = name self.base_storages = base_storages def open(self): name = self.name if name in self.base_storages: raise ValueError("Duplicate database name: %r" % name) storage = DemoStorage("Memory storage %r" % name) self.base_storages[name] = storage return DB(storage, database_name=name) class DerivedDatabaseFactory(object): """Factory object for passing to appsetup.multi_databases This class is an internal implementation detail, subject to change without notice! It is currently used by FunctionalTestSetUp.setUp to create the derived storage(s) used for each test in a layer. The constructor takes the name of the new database, and a dictionary of storages. The 'open' method creates a new DemoStorage as a wrapper around the storage with the given name. Then creates and returns a named DB object using the storage. """ def __init__(self, name, base_storages): self.name = name self.storage = DemoStorage("Demo storage %r" % name, base_storages[name]) def open(self): return DB(self.storage, database_name=self.name) class FunctionalTestSetup(object): """Keeps shared state across several functional test cases.""" __shared_state = {'_init': False} def __init__(self, config_file=None, database_names=None, product_config=None): """Initializes Zope 3 framework. Creates a volatile memory storage. Parses Zope3 configuration files. """ self.__dict__ = self.__shared_state if database_names is not None: database_names = tuple(database_names) if not self._init: # Make sure unit tests are cleaned up zope.app.testing.setup.placefulSetUp() zope.app.testing.setup.placefulTearDown() if not config_file: config_file = 'ftesting.zcml' if database_names is None: database_names = ('unnamed',) self.log = StringIO() # Make it silent but keep the log available for debugging logging.root.addHandler(logging.StreamHandler(self.log)) self.old_product_config = copy.deepcopy( zope.app.appsetup.product.saveConfiguration()) configs = [] if product_config: configs = zope.app.appsetup.product.loadConfiguration( StringIO(product_config)) configs = [ zope.app.appsetup.product.FauxConfiguration(name, values) for name, values in configs.items()] self.local_product_config = configs zope.app.appsetup.product.setProductConfigurations(configs) self._base_storages = {} self.db = multi_database( BaseDatabaseFactory(name, self._base_storages) for name in database_names)[0][0] # This handles anything added by generations or other bootstrap # subscribers. commit() self.dbstack = [] self.app = Debugger(self.db, config_file) self.connection = None self._config_file = config_file self._product_config = product_config self._database_names = database_names self._init = True # Make a local grant for the test user setup = component.queryUtility(IManagerSetup) if setup is not None: setup.setUpManager() FunctionalTestSetup().connection = None elif config_file and config_file != self._config_file: # Running different tests with different configurations is not # supported at the moment raise NotImplementedError('Already configured' ' with a different config file') elif product_config and product_config != self._product_config: raise NotImplementedError('Already configured' ' with different product configuration') elif database_names and database_names != self._database_names: # Running different tests with different configurations is not # supported at the moment raise NotImplementedError('Already configured' ' with different database names') # BBB: Simulate the old base_storage attribute, but only when not using # multiple databases. There *is* code in the wild that uses the attribute. def _get_base_storage(self): if len(self._database_names) != 1: raise AttributeError('base_storage') return self._base_storages[self._database_names[0]] def _set_base_storage(self, value): if len(self._database_names) != 1: raise AttributeError('base_storage') self._base_storages[self._database_names[0]] = value base_storage = property(_get_base_storage, _set_base_storage) def _close_databases(self): # This is really careful to unregister the databases before attempting # to close anything. Zope Corporation has a couple of large # multi-database applications that get bitten if we're not careful # like this, but we've not been able to write a concise test case yet. base = component.getGlobalSiteManager() dbs = [] for name, db in list(component.getUtilitiesFor(IDatabase)): ok = base.unregisterUtility(db, IDatabase, name) assert ok dbs.append(db) abort() if self.connection: self.connection.close() self.connection = None for db in dbs: db.close() def setUp(self): """Prepares for a functional test case.""" # Tear down the old demo storages (if any) and create fresh ones abort() self.dbstack.append((self.db, self.connection)) self.connection = None zope.app.appsetup.product.setProductConfigurations( self.local_product_config) self.db = self.app.db = multi_database( DerivedDatabaseFactory(name, self._base_storages) for name in self._database_names)[0][0] def tearDown(self): """Cleans up after a functional test case.""" self._close_databases() self.db, self.connection = self.dbstack.pop() setSite(None) def tearDownCompletely(self): """Cleans up the setup done by the constructor.""" self._close_databases() assert self.dbstack == [] zope.app.testing.setup.placefulTearDown() zope.app.appsetup.product.restoreConfiguration( self.old_product_config) self._config_file = False self._product_config = None self._database_names = None self._init = False def getRootFolder(self): """Returns the Zope root folder.""" if not self.connection: self.connection = self.db.open() root = self.connection.root() return root[ZopePublication.root_name] def getApplication(self): """Returns the Zope application instance.""" return self.app class ZCMLLayer: """ZCML-defined test layer """ __bases__ = () def __init__(self, config_file, module, name, allow_teardown=False, product_config=None): self.config_file = config_file self.__module__ = module self.__name__ = name self.allow_teardown = allow_teardown self.product_config = product_config def setUp(self): self.setup = FunctionalTestSetup( self.config_file, product_config=self.product_config) def tearDown(self): self.setup.tearDownCompletely() if not self.allow_teardown: # Some ZCML directives change globals but are not accompanied # with registered CleanUp handlers to undo the changes. Let # packages which use such directives indicate that they do not # support tearing down. raise NotImplementedError def defineLayer(name, zcml='test.zcml', allow_teardown=False): """Helper function for defining layers. Usage: defineLayer('foo') """ globals = sys._getframe(1).f_globals globals[name] = ZCMLLayer( os.path.join(os.path.dirname(globals['__file__']), zcml), globals['__name__'], name, allow_teardown=allow_teardown, ) if os.path.exists(os.path.join('zopeskel', 'etc', 'ftesting.zcml')): Functional = os.path.join('zopeskel', 'etc', 'ftesting.zcml') FunctionalNoDevMode = os.path.join('zopeskel', 'etc', 'ftesting-base.zcml') elif os.path.exists(os.path.join('etc', 'ftesting.zcml')): Functional = os.path.join('etc', 'ftesting.zcml') FunctionalNoDevMode = os.path.join('etc', 'ftesting-base.zcml') else: # let's hope that the file is in our CWD. If not, we'll get an # error anyways, but we can't just throw an error if we don't find # that file. This module might be imported for other things as # well, not only starting up Zope from ftesting.zcml. Functional = 'ftesting.zcml' FunctionalNoDevMode = 'ftesting-base.zcml' Functional = os.path.abspath(Functional) FunctionalNoDevMode = os.path.abspath(FunctionalNoDevMode) Functional = ZCMLLayer(Functional, __name__, 'Functional') FunctionalNoDevMode = ZCMLLayer(FunctionalNoDevMode, __name__, 'FunctionalNoDevMode') class FunctionalTestCase(unittest.TestCase): """Functional test case.""" layer = Functional def setUp(self): """Prepares for a functional test case.""" super(FunctionalTestCase, self).setUp() FunctionalTestSetup().setUp() def tearDown(self): """Cleans up after a functional test case.""" FunctionalTestSetup().tearDown() super(FunctionalTestCase, self).tearDown() def getRootFolder(self): """Returns the Zope root folder.""" return FunctionalTestSetup().getRootFolder() def commit(self): commit() def abort(self): abort() class CookieHandler(object): def __init__(self, *args, **kw): # Somewhere to store cookies between consecutive requests self.cookies = SimpleCookie() super(CookieHandler, self).__init__(*args, **kw) def httpCookie(self, path): """Return self.cookies as an HTTP_COOKIE environment value.""" l = [m.OutputString().split(';')[0] for m in self.cookies.values() if path.startswith(m['path'])] return '; '.join(l) def loadCookies(self, envstring): self.cookies.load(envstring) def saveCookies(self, response): """Save cookies from the response.""" # Urgh - need to play with the response's privates to extract # cookies that have been set # TODO: extend the IHTTPRequest interface to allow access to all # cookies # TODO: handle cookie expirations for k, v in response._cookies.items(): k = k.encode('utf8') self.cookies[k] = v['value'].encode('utf8') if 'path' in v: self.cookies[k]['path'] = v['path'] class BrowserTestCase(CookieHandler, FunctionalTestCase): """Functional test case for Browser requests.""" def setSite(self, site): """Set the site which will be used to look up local components""" setSite(site) def getSite(self): """Returns the site which is used to look up local components""" return getSite() def makeRequest(self, path='', basic=None, form=None, env={}): """Creates a new request object. Arguments: path -- the path to be traversed (e.g. "/folder1/index.html") basic -- basic HTTP authentication credentials ("user:password") form -- a dictionary emulating a form submission (Note that field values should be Unicode strings) env -- a dictionary of additional environment variables (You can emulate HTTP request header X-Header: foo by adding 'HTTP_X_HEADER': 'foo' to env) """ environment = {"HTTP_HOST": 'localhost', "HTTP_COOKIE": self.httpCookie(path)} environment.update(env) app = FunctionalTestSetup().getApplication() request = app._request(path, '', environment=environment, basic=basic, form=form, request=BrowserRequest) setDefaultSkin(request) return request def publish(self, path, basic=None, form=None, env={}, handle_errors=False): """Renders an object at a given location. Arguments are the same as in makeRequest with the following exception: handle_errors -- if False (default), exceptions will not be caught if True, exceptions will return a formatted error page. Returns the response object enhanced with the following methods: getOutput() -- returns the full HTTP output as a string getBody() -- returns the full response body as a string getPath() -- returns the path used in the request """ old_site = self.getSite() self.setSite(None) # A cookie header has been sent - ensure that future requests # in this test also send the cookie, as this is what browsers do. # We pull it apart and reassemble the header to block cookies # with invalid paths going through, which may or may not be correct if 'HTTP_COOKIE' in env: self.loadCookies(env['HTTP_COOKIE']) del env['HTTP_COOKIE'] # Added again in makeRequest request = self.makeRequest(path, basic=basic, form=form, env=env) if 'HTTP_COOKIE' in env: self.loadCookies(env['HTTP_COOKIE']) request = publish(request, handle_errors=handle_errors) response = ResponseWrapper(request.response, path, request) self.saveCookies(response) self.setSite(old_site) return response def checkForBrokenLinks(self, body, path, basic=None): """Looks for broken links in a page by trying to traverse relative URIs. """ if not body: return old_site = self.getSite() self.setSite(None) from htmllib import HTMLParser from formatter import NullFormatter class SimpleHTMLParser(HTMLParser): def __init__(self, fmt, base): HTMLParser.__init__(self, fmt) self.base = base def do_base(self, attrs): self.base = dict(attrs).get('href', self.base) parser = SimpleHTMLParser(NullFormatter(), path) parser.feed(body) parser.close() base = parser.base while not base.endswith('/'): base = base[:-1] if base.startswith('http://localhost/'): base = base[len('http://localhost/') - 1:] errors = [] for a in parser.anchorlist: if a.startswith('http://localhost/'): a = a[len('http://localhost/') - 1:] elif a.find(':') != -1: # Assume it is an external link continue elif not a.startswith('/'): a = base + a if a.find('#') != -1: a = a[:a.index('#')] # ??? what about queries (/path/to/foo?bar=baz&etc)? request = None try: try: request = self.makeRequest(a, basic=basic) publication = request.publication request.processInputs() publication.beforeTraversal(request) object = publication.getApplication(request) object = request.traverse(object) publication.afterTraversal(request, object) except (KeyError, NameError, AttributeError, Unauthorized, Forbidden): e = traceback.format_exception_only( *sys.exc_info()[:2])[-1] errors.append((a, e.strip())) finally: publication.endRequest(request, object) self.setSite(old_site) # Make sure we don't have pending changes abort() # The request should always be closed to free resources # held by the request if request: request.close() if errors: self.fail("%s contains broken links:\n" % path + "\n".join([" %s:\t%s" % (a, e) for a, e in errors])) class HTTPTestCase(FunctionalTestCase): """Functional test case for HTTP requests.""" def makeRequest(self, path='', basic=None, form=None, env={}, instream=None): """Creates a new request object. Arguments: path -- the path to be traversed (e.g. "/folder1/index.html") basic -- basic HTTP authentication credentials ("user:password") form -- a dictionary emulating a form submission (Note that field values should be Unicode strings) env -- a dictionary of additional environment variables (You can emulate HTTP request header X-Header: foo by adding 'HTTP_X_HEADER': 'foo' to env) instream -- a stream from where the HTTP request will be read """ if instream is None: instream = '' environment = {"HTTP_HOST": 'localhost'} environment.update(env) app = FunctionalTestSetup().getApplication() request = app._request(path, instream, environment=environment, basic=basic, form=form, request=HTTPRequest, publication=HTTPPublication) return request def publish(self, path, basic=None, form=None, env={}, handle_errors=False, request_body=''): """Renders an object at a given location. Arguments are the same as in makeRequest with the following exception: handle_errors -- if False (default), exceptions will not be caught if True, exceptions will return a formatted error page. Returns the response object enhanced with the following methods: getOutput() -- returns the full HTTP output as a string getBody() -- returns the full response body as a string getPath() -- returns the path used in the request """ request = self.makeRequest(path, basic=basic, form=form, env=env, instream=request_body) response = ResponseWrapper(request.response, path, request) publish(request, handle_errors=handle_errors) return response headerre = re.compile(r'(\S+): (.+)$') basicre = re.compile('Basic (.+)?:(.+)?$') def split_header(header): return headerre.match(header).group(1, 2) def auth_header(header): match = basicre.match(header) if match: import base64 u, p = match.group(1, 2) if u is None: u = '' if p is None: p = '' auth = base64.encodestring('%s:%s' % (u, p)) return 'Basic %s' % auth[:-1] return header def getRootFolder(): return FunctionalTestSetup().getRootFolder() def sync(): getRootFolder()._p_jar.sync() # Sample functional test case class SampleFunctionalTest(BrowserTestCase): def testRootPage(self): response = self.publish('/') self.assertEquals(response.getStatus(), 200) def testRootPage_preferred_languages(self): response = self.publish('/', env={'HTTP_ACCEPT_LANGUAGE': 'en'}) self.assertEquals(response.getStatus(), 200) def testNotExisting(self): response = self.publish('/nosuchthing', handle_errors=True) self.assertEquals(response.getStatus(), 404) def testLinks(self): response = self.publish('/') self.assertEquals(response.getStatus(), 200) self.checkForBrokenLinks(response.consumeBody(), response.getPath()) def sample_test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(SampleFunctionalTest)) return suite class HTTPCaller(CookieHandler): """Execute an HTTP request string via the publisher""" def __call__(self, request_string, handle_errors=True, form=None): # Commit work done by previous python code. commit() # Discard leading white space to make call layout simpler request_string = request_string.lstrip() # split off and parse the command line l = request_string.find('\n') command_line = request_string[:l].rstrip() request_string = request_string[l + 1:] method, path, protocol = command_line.split() instream = StringIO(request_string) environment = {"HTTP_COOKIE": self.httpCookie(path), "HTTP_HOST": 'localhost', "REQUEST_METHOD": method, "SERVER_PROTOCOL": protocol, "REMOTE_ADDR": '127.0.0.1', } headers = [split_header(header) for header in rfc822.Message(instream).headers] for name, value in headers: name = ('_'.join(name.upper().split('-'))) if name not in ('CONTENT_TYPE', 'CONTENT_LENGTH'): name = 'HTTP_' + name environment[name] = value.rstrip() auth_key = 'HTTP_AUTHORIZATION' if auth_key in environment: environment[auth_key] = auth_header(environment[auth_key]) old_site = getSite() setSite(None) request_cls, publication_cls = self.chooseRequestClass(method, path, environment) app = FunctionalTestSetup().getApplication() request = app._request( path, instream, environment=environment, request=request_cls, publication=publication_cls) if ISkinnable.providedBy(request): # only ISkinnable requests have skins setDefaultSkin(request) if form is not None: if request.form: raise ValueError("only one set of form values can be provided") request.form = form request = publish(request, handle_errors=handle_errors) response = ResponseWrapper( request.response, path, request, omit=('x-content-type-warning', 'x-powered-by'), ) self.saveCookies(response) setSite(old_site) # sync Python connection: getRootFolder()._p_jar.sync() return response def chooseRequestClass(self, method, path, environment): """Choose and return a request class and a publication class""" # note that `path` is unused by the default implementation (BBB) return chooseClasses(method, environment) def FunctionalDocFileSuite(*paths, **kw): """Build a functional test suite from a text file.""" kw['package'] = doctest._normalize_module(kw.get('package')) _prepare_doctest_keywords(kw) suite = doctest.DocFileSuite(*paths, **kw) suite.layer = Functional return suite def FunctionalDocTestSuite(*paths, **kw): """Build a functional test suite from docstrings in a module.""" _prepare_doctest_keywords(kw) suite = doctest.DocTestSuite(*paths, **kw) suite.layer = Functional return suite def _prepare_doctest_keywords(kw): globs = kw.setdefault('globs', {}) globs['getRootFolder'] = getRootFolder globs['sync'] = sync kwsetUp = kw.get('setUp') def setUp(test): test.globs['http'] = HTTPCaller() FunctionalTestSetup().setUp() if kwsetUp is not None: kwsetUp(test) kw['setUp'] = setUp kwtearDown = kw.get('tearDown') def tearDown(test): if kwtearDown is not None: kwtearDown(test) FunctionalTestSetup().tearDown() kw['tearDown'] = tearDown if 'optionflags' not in kw: old = doctest.set_unittest_reportflags(0) doctest.set_unittest_reportflags(old) kw['optionflags'] = (old | doctest.ELLIPSIS | doctest.REPORT_NDIFF | doctest.NORMALIZE_WHITESPACE) zope.app.testing-3.10.0/src/zope/app/testing/testbrowser.py0000644000175000017500000000650111704135707022070 0ustar jimjimimport sys from zope.app.testing.functional import HTTPCaller import zope.testbrowser.connection class PublisherConnection(object): """A ``mechanize`` compatible connection object.""" def __init__(self, host, timeout=None): self.caller = HTTPCaller() self.host = host def set_debuglevel(self, level): pass def _quote(self, url): # the publisher expects to be able to split on whitespace, so we have # to make sure there is none in the URL return url.replace(' ', '%20') def request(self, method, url, body=None, headers=None): """Send a request to the publisher. The response will be stored in ``self.response``. """ if body is None: body = '' if url == '': url = '/' url = self._quote(url) # Extract the handle_error option header if sys.version_info >= (2,5): handle_errors_key = 'X-Zope-Handle-Errors' else: handle_errors_key = 'X-zope-handle-errors' handle_errors_header = headers.get(handle_errors_key, True) if handle_errors_key in headers: del headers[handle_errors_key] # Translate string to boolean. handle_errors = {'False': False}.get(handle_errors_header, True) # Construct the headers. header_chunks = [] if headers is not None: for header in headers.items(): header_chunks.append('%s: %s' % header) headers = '\n'.join(header_chunks) + '\n' else: headers = '' # Construct the full HTTP request string, since that is what the # ``HTTPCaller`` wants. request_string = (method + ' ' + url + ' HTTP/1.1\n' + headers + '\n' + body) self.response = self.caller(request_string, handle_errors) def getresponse(self): """Return a ``mechanize`` compatible response. The goal of ths method is to convert the Zope Publisher's reseponse to a ``mechanize`` compatible response, which is also understood by mechanize. """ real_response = self.response._response status = real_response.getStatus() reason = real_response._reason # XXX add a getReason method headers = real_response.getHeaders() headers.sort() headers.insert(0, ('Status', real_response.getStatusString())) headers = '\r\n'.join('%s: %s' % h for h in headers) content = real_response.consumeBody() return zope.testbrowser.connection.Response(content, headers, status, reason) class PublisherHTTPHandler(zope.testbrowser.connection.HTTPHandler): """Special HTTP handler to use the Zope Publisher.""" def _connect(self, *args, **kw): return PublisherConnection(*args, **kw) class PublisherMechanizeBrowser(zope.testbrowser.connection.MechanizeBrowser): """Special ``mechanize`` browser using the Zope Publisher HTTP handler.""" def _http_handler(self, *args, **kw): return PublisherHTTPHandler(*args, **kw) class Browser(zope.testbrowser.browser.Browser): """A Zope `testbrowser` Browser that uses the Zope Publisher.""" def __init__(self, url=None): mech_browser = PublisherMechanizeBrowser() super(Browser, self).__init__(url=url, mech_browser=mech_browser) zope.app.testing-3.10.0/src/zope/app/testing/dochttp.txt0000644000175000017500000000176111704135707021344 0ustar jimjim================= FDocTest (How-To) ================= Steps to get started: 1. Use a clean/missing Data.fs 2. Create a manager with the name "mgr", password "mgrpw", and grant the zope.Manager role. 3. Install tcpwatch. 4. Create a temporary directory to record tcpwatch output. 5. Run tcpwatch using: tcpwatch.py -L 8081:8080 -s -r tmpdir (the ports are the listening port and forwarded-to port; the second need to match the Zope configuration) 6. In a browser, connect to the listening port and do whatever needs to be recorded. 7. Shut down tcpwatch. 8. Run the script src/zope/app/testing/dochttp.py: python2.4 src/zope/app/testing/dochttp.py tmpdir > somefile.txt 9. Edit the generated text file to add explanations and elide uninteresting portions of the output. 10. In a functional test module (usually ftests.py), import FunctionalDocFileSuite from zope.app.testing.functional and instantiate it, passing the name of the text file containing the test. zope.app.testing-3.10.0/src/zope/app/testing/testing.py0000644000175000017500000000324311704135707021162 0ustar jimjim############################################################################## # # Copyright (c) 2007 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """zope.app.testing common test related classes/functions/objects. $Id: testing.py 110724 2010-04-11 00:04:11Z tseaver $ """ __docformat__ = "reStructuredText" import os from ZODB.POSException import ConflictError from zope import interface from zope import component import zope.publisher.interfaces.browser from zope.app.testing.functional import ZCMLLayer AppTestingLayer = ZCMLLayer( os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'), __name__, 'AppTestingLayer', allow_teardown=True) class IFailingKlass(interface.Interface): pass class FailingKlass(object): interface.implements(IFailingKlass) class ConflictRaisingView(object): __used_for__ = IFailingKlass interface.implements(zope.publisher.interfaces.browser.IBrowserPublisher) component.adapts(interface.Interface, zope.publisher.interfaces.browser.IBrowserRequest) def __init__(self, context, request): pass def browserDefault(self, *_): return self, () def __call__(self): raise ConflictError zope.app.testing-3.10.0/src/zope/app/testing/empty.zcml0000644000175000017500000000013411704135707021154 0ustar jimjim zope.app.testing-3.10.0/src/zope/app/testing/recorded/0000755000175000017500000000000011704136013020707 5ustar jimjimzope.app.testing-3.10.0/src/zope/app/testing/recorded/test0002.request0000644000175000017500000001275411704135707023624 0ustar jimjimGET /@@/zope3.css HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/css,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/@@contents.html If-Modified-Since: Thu, 19 Aug 2004 10:10:06 GMT Authorization: Basic bWdyOm1ncnB3 GET /@@/onlinehelp.js HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: */* Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/@@contents.html If-Modified-Since: Thu, 19 Aug 2004 10:10:06 GMT Authorization: Basic bWdyOm1ncnB3 GET /@@/xmltree.js HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: */* Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/@@contents.html If-Modified-Since: Thu, 19 Aug 2004 10:10:06 GMT Authorization: Basic bWdyOm1ncnB3 GET /@@/favicon.png HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive If-Modified-Since: Thu, 19 Aug 2004 10:10:06 GMT Authorization: Basic bWdyOm1ncnB3 GET /@@/zope3logo.gif HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/@@contents.html If-Modified-Since: Thu, 19 Aug 2004 10:10:04 GMT Authorization: Basic bWdyOm1ncnB3 GET /@@singleBranchTree.xml HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Authorization: Basic bWdyOm1ncnB3 GET /@@/zope-app-folder-interfaces-IFolder-zmi_icon.gif HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/@@contents.html If-Modified-Since: Thu, 19 Aug 2004 10:10:08 GMT Authorization: Basic bWdyOm1ncnB3 GET / HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Authorization: Basic bWdyOm1ncnB3 GET /@@children.xml HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Authorization: Basic bWdyOm1ncnB3 GET /@@/zope-app-site-interfaces-ISiteManager-zmi_icon.gif HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/ Authorization: Basic bWdyOm1ncnB3 GET /++etc++site/@@tasks.html HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/ Authorization: Basic bWdyOm1ncnB3 GET /++etc++site/@@singleBranchTree.xml HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Authorization: Basic bWdyOm1ncnB3 zope.app.testing-3.10.0/src/zope/app/testing/recorded/test0001.request0000644000175000017500000000617411704135707023622 0ustar jimjimGET /@@contents.html HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive GET /@@contents.html HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Authorization: Basic bWdyOm1ncnB3 GET /@@/pl.gif HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/@@contents.html If-Modified-Since: Thu, 19 Aug 2004 10:10:04 GMT Authorization: Basic bWdyOm1ncnB3 GET /@@singleBranchTree.xml HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Authorization: Basic bWdyOm1ncnB3 GET /@@/mi.gif HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/ Authorization: Basic bWdyOm1ncnB3 GET /++etc++site/@@manage HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/ Authorization: Basic bWdyOm1ncnB3 GET /@@/site_management.css HTTP/1.1 Host: localhost:8081 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Accept: text/css,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8081/++etc++site/@@tasks.html Authorization: Basic bWdyOm1ncnB3 zope.app.testing-3.10.0/src/zope/app/testing/recorded/test0002.response0000644000175000017500000001165511704135707023771 0ustar jimjimHTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:14 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:14 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:14 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:14 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:14 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 200 OK Content-Length: 183 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Expires: Fri, 13 Aug 2004 10:35:15 GMT Server: zope.server.http (HTTP) Pragma: no-cache Cache-Control: no-cache Date: Fri, 20 Aug 2004 10:35:15 GMT Content-Type: text/xml;charset=utf-8 HTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:15 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 200 OK X-Content-Type-Warning: guessed from content Content-Length: 89 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:27 GMT Content-Type: text/html;charset=utf-8 Server: zope.server.http (HTTP) ... HTTP/1.1 200 OK Content-Length: 175 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Expires: Fri, 13 Aug 2004 10:35:47 GMT Server: zope.server.http (HTTP) Pragma: no-cache Cache-Control: no-cache Date: Fri, 20 Aug 2004 10:35:47 GMT Content-Type: text/xml;charset=utf-8 HTTP/1.1 200 OK Last-Modified: Thu, 19 Aug 2004 10:09:00 GMT Content-Length: 932 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:47 GMT Cache-Control: public,max-age=86400 Content-Type: image/gif Server: zope.server.http (HTTP) GIF89a÷NNN¨oÿ ñï¶Wâã*çèEííqíí{‹‹‹îî†îî‡ïï‘ðð›ùâ¼ðð£òò­ôôÀõõËööÐøøÚùùâúúçúúëúúíýýôþþúÿÿÿ!ù,H° Áƒ(D€p  ÐP‚ 2À‘ã‡B6Ð02$D-jÈ€a€† <` `£@rº ÓÁ‚6¸ ¹3d€‚"Àt§Óœ-b°@ahQ¢7/T˜0¡éK¦¢"Шq§Æ¨:ª 6eÅ·;HTTP/1.1 200 OK X-Content-Type-Warning: guessed from content Content-Length: 89 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:51 GMT Content-Type: text/html;charset=utf-8 Server: zope.server.http (HTTP) ... HTTP/1.1 200 OK Content-Length: 325 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Expires: Fri, 13 Aug 2004 10:35:52 GMT Server: zope.server.http (HTTP) Pragma: no-cache Cache-Control: no-cache Date: Fri, 20 Aug 2004 10:35:52 GMT Content-Type: text/xml;charset=utf-8 zope.app.testing-3.10.0/src/zope/app/testing/recorded/test0001.response0000644000175000017500000000753411704135707023771 0ustar jimjimHTTP/1.1 401 Unauthorized X-Content-Type-Warning: guessed from content Content-Length: 89 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:05 GMT Content-Type: text/html;charset=utf-8 WWW-Authenticate: basic realm="Zope" Server: zope.server.http (HTTP) ... HTTP/1.1 200 OK X-Content-Type-Warning: guessed from content Content-Length: 89 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:13 GMT Content-Type: text/html;charset=utf-8 Server: zope.server.http (HTTP) ... HTTP/1.1 304 Not Modified X-Content-Type-Warning: guessed from content Content-Length: 0 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:15 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 200 OK Content-Length: 183 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Expires: Fri, 13 Aug 2004 10:35:28 GMT Server: zope.server.http (HTTP) Pragma: no-cache Cache-Control: no-cache Date: Fri, 20 Aug 2004 10:35:28 GMT Content-Type: text/xml;charset=utf-8 HTTP/1.1 200 OK Last-Modified: Thu, 19 Aug 2004 10:10:06 GMT Content-Length: 868 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:47 GMT Cache-Control: public,max-age=86400 Content-Type: image/gif Server: zope.server.http (HTTP) GIF89a÷ÿÿPPP€€€ÀÀÀÿ€@ @€€€@@ÿÿÿÿ€€€@€€ÿÿÿ!ù,@AH° Á*|0À „ 6tH±¢Åƒ%:„qâÅ IräÆŒ OX¹2¥AŽ =,Y2¤M‡;HTTP/1.1 303 See Other X-Content-Type-Warning: guessed from content Content-Length: 0 Location: @@tasks.html X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:51 GMT Content-Type: text/plain;charset=utf-8 Server: zope.server.http (HTTP) HTTP/1.1 200 OK Last-Modified: Thu, 19 Aug 2004 10:10:04 GMT Content-Length: 738 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Date: Fri, 20 Aug 2004 10:35:52 GMT Cache-Control: public,max-age=86400 Content-Type: text/css;charset=utf-8 Server: zope.server.http (HTTP) /* ** Customisations for the Site Management view ** Used when the URL contains ++etc++site */ a { color: #963; } #actions { background: #963; border-left: 1px solid #963; border-right: 1px solid #963; } #actions a { color: White; border-left: 1px dashed white; } #actions a:hover { color: black; background-color: White; } #breadcrumbs { border-bottom: 1px solid #963; } .itemViews { border-bottom: 1px solid #963; } .itemViews a { border: 1px solid #963; } .itemViews a.selected { background: #963; border-bottom: #963 1px solid; } .itemViews a:hover { background-color: #963; color: White; } hr { color: #963; } h1, h2, h3, h4, h5, h6 { border-bottom: 1px solid #963; } zope.app.testing-3.10.0/src/zope/app/testing/cookieTestTwo.txt0000644000175000017500000000337511704135707022505 0ustar jimjim======================== DocTest Functional Tests ======================== This file documents and tests doctest-based functional tests and basic Zope web-application functionality. This second DocTest, zope/app/testing/cookieTestTwo.txt, has specifically been created in order to make sure cookie information is not being saved across a test suite. If we are saving these via a global 'http' instance, we will see more results than those listed below. 'http' is instead created in setUp within _prepare_doctest_keywords, rather than in the global declarations. >>> from zope.app.testing import functional >>> from zope.app.testing.tests import DummyCookiesResponse >>> response = DummyCookiesResponse(dict( ... cobalt=dict(value='fromCookieTestTwo', ... path='/foo', ... comment='rest is ignored'), ... crimson=dict(value='fromCookieTestTwo'))) >>> http.saveCookies(response) >>> len(http.cookies) 2 >>> http.cookies['cobalt'].OutputString() 'cobalt=fromCookieTestTwo; Path=/foo...' >>> http.cookies >>> http.cookies['cobalt'] = 'fromCookieTestTwo' >>> http.cookies['cobalt']['path'] = '/foo' >>> http.cookies['amber'] = 'fromCookieTestTwo' >>> http.cookies['amber']['path'] = '/foo/baz' >>> http.cookies['crimson'] = 'fromCookieTestTwo' >>> cookieHeader = http.httpCookie('/foo/bar') >>> parts = cookieHeader.split('; ') >>> parts.sort() >>> parts ['cobalt=fromCookieTestTwo', 'crimson=fromCookieTestTwo'] >>> cookieHeader = http.httpCookie('/foo/baz') >>> parts = cookieHeader.split('; ') >>> parts.sort() >>> parts ['amber=fromCookieTestTwo', 'cobalt=fromCookieTestTwo', 'crimson=fromCookieTestTwo'] zope.app.testing-3.10.0/src/zope/app/testing/ztapi.py0000644000175000017500000000750311704135707020637 0ustar jimjim############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """Testing helper functions $Id: ztapi.py 110724 2010-04-11 00:04:11Z tseaver $ """ import zope.interface import zope.component from zope.publisher.browser import IBrowserRequest from zope.publisher.interfaces import IDefaultViewName from zope.publisher.interfaces.browser import IDefaultBrowserLayer from zope.traversing.interfaces import ITraversable def provideView(for_, type, providing, name, factory, layer=None): if layer is None: layer = type provideAdapter(for_, providing, factory, name, (layer,)) def provideMultiView(for_, type, providing, name, factory, layer=None): if layer is None: layer = type provideAdapter(for_[0], providing, factory, name, tuple(for_[1:])+(layer,)) def browserView(for_, name, factory, layer=IDefaultBrowserLayer, providing=zope.interface.Interface): """Define a global browser view """ if isinstance(factory, (list, tuple)): raise ValueError("Factory cannot be a list or tuple") provideAdapter(for_, providing, factory, name, (layer,)) def browserViewProviding(for_, factory, providing, layer=IDefaultBrowserLayer): """Define a view providing a particular interface.""" if isinstance(factory, (list, tuple)): raise ValueError("Factory cannot be a list or tuple") return browserView(for_, '', factory, layer, providing) def browserResource(name, factory, layer=IDefaultBrowserLayer, providing=zope.interface.Interface): """Define a global browser view """ if isinstance(factory, (list, tuple)): raise ValueError("Factory cannot be a list or tuple") provideAdapter((layer,), providing, factory, name) def setDefaultViewName(for_, name, layer=IDefaultBrowserLayer, type=IBrowserRequest): if layer is None: layer = type gsm = zope.component.getGlobalSiteManager() gsm.registerAdapter(name, (for_, layer), IDefaultViewName, '') stypes = list, tuple def provideAdapter(required, provided, factory, name='', with_=(), **kw): if with_ is None and kw.has_key('with'): with_ = kw['with'] if isinstance(factory, (list, tuple)): raise ValueError("Factory cannot be a list or tuple") gsm = zope.component.getGlobalSiteManager() if with_: required = (required, ) + tuple(with_) elif not isinstance(required, stypes): required = (required,) gsm.registerAdapter(factory, required, provided, name, event=False) def subscribe(required, provided, factory): gsm = zope.component.getGlobalSiteManager() if provided is None: gsm.registerHandler(factory, required, event=False) else: gsm.registerSubscriptionAdapter(factory, required, provided, event=False) def provideUtility(provided, component, name=''): gsm = zope.component.getGlobalSiteManager() gsm.registerUtility(component, provided, name, event=False) def unprovideUtility(provided, name=''): gsm = zope.component.getGlobalSiteManager() gsm.unregisterUtility(provided=provided, name=name) def provideNamespaceHandler(name, handler): provideAdapter(None, ITraversable, handler, name=name) provideView(None, None, ITraversable, name, handler) zope.app.testing-3.10.0/src/zope/app/testing/testbrowser.txt0000644000175000017500000000407611704135707022264 0ustar jimjimZope Publisher Browser Tests ============================ These tests specifically test the implementation of Browser which uses the Zope Publisher via zope.app.testing as the application to test. >>> from zope.app.testing.testbrowser import Browser >>> browser = Browser() Error Handling -------------- handleErrors works as advertised: >>> browser.handleErrors True >>> browser.open('http://localhost/invalid') Traceback (most recent call last): ... HTTPError: HTTP Error 404: Not Found So when we tell the publisher not to handle the errors, >>> browser.handleErrors = False >>> browser.open('http://localhost/invalid') Traceback (most recent call last): ... NotFound: Object: , name: u'invalid' Spaces in URLs -------------- Spaces in URLs don't cause blowups: >>> browser.open('http://localhost/space here') Traceback (most recent call last): ... NotFound: Object: , name: u'space here' Headers ------- Sending arbitrary headers works: >>> browser.addHeader('Accept-Language', 'en-US') >>> browser.open('http://localhost/echo_one?var=HTTP_ACCEPT_LANGUAGE') >>> print browser.contents 'en-US' POST ---- HTTP posts are correctly sent: >>> browser.post('http://localhost/echo', 'x=1&y=2') >>> print browser.contents CONTENT_LENGTH: 7 CONTENT_TYPE: application/x-www-form-urlencoded HTTP_ACCEPT_LANGUAGE: en-US HTTP_CONNECTION: close HTTP_COOKIE: HTTP_HOST: localhost HTTP_USER_AGENT: Python-urllib/2.4 PATH_INFO: /echo QUERY_STRING: REMOTE_ADDR: 127.0.0.1 REQUEST_METHOD: POST SERVER_PROTOCOL: HTTP/1.1 x: 1 y: 2 Body: '' Returned headers ---------------- Server headers are correctly returned: >>> print browser.headers Status: 200 OK Content-Length: 123 Content-Type: text/plain;charset=utf-8 X-Content-Type-Warning: guessed from content X-Powered-By: Zope (www.zope.org), Python (www.python.org) zope.app.testing-3.10.0/src/zope/app/testing/tests.py0000644000175000017500000005530711704135707020657 0ustar jimjim############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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 tcpdoc $Id: tests.py 123984 2012-01-07 17:43:12Z menesis $ """ from doctest import DocTestSuite import os import re import unittest import StringIO from zope.testing.renormalizing import RENormalizing from zope.component import getAllUtilitiesRegisteredFor from ZODB.interfaces import IDatabase import zope.app.testing from zope.app.publication.requestpublicationregistry import factoryRegistry from zope.app.publication.requestpublicationfactories import BrowserFactory from zope.app.testing import functional from zope.app.testing.dochttp import dochttp import transaction from zope.app.testing.functional import SampleFunctionalTest from zope.app.testing.functional import BrowserTestCase, HTTPTestCase from zope.app.testing.functional import FunctionalDocFileSuite from zope.app.testing.functional import FunctionalTestCase from zope.app.testing.functional import FunctionalTestSetup from zope.app.testing.testing import AppTestingLayer from zope.app.testing.testing import FailingKlass HEADERS = """\ HTTP/1.1 200 OK Content-Type: text/plain """ BODY = """\ This is the response body. """ here = os.path.dirname(zope.app.testing.__file__) directory = os.path.join(here, 'recorded') expected = r''' >>> print http(r""" ... GET /@@contents.html HTTP/1.1 ... """) HTTP/1.1 401 Unauthorized Content-Length: 89 Content-Type: text/html;charset=utf-8 Www-Authenticate: basic realm="Zope" ... >>> print http(r""" ... GET /@@contents.html HTTP/1.1 ... Authorization: Basic bWdyOm1ncnB3 ... """) HTTP/1.1 200 OK Content-Length: 89 Content-Type: text/html;charset=utf-8 ... >>> print http(r""" ... GET /++etc++site/@@manage HTTP/1.1 ... Authorization: Basic bWdyOm1ncnB3 ... Referer: http://localhost:8081/ ... """) HTTP/1.1 303 See Other Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@tasks.html >>> print http(r""" ... GET / HTTP/1.1 ... Authorization: Basic bWdyOm1ncnB3 ... """) HTTP/1.1 200 OK Content-Length: 89 Content-Type: text/html;charset=utf-8 ... >>> print http(r""" ... GET /++etc++site/@@tasks.html HTTP/1.1 ... Authorization: Basic bWdyOm1ncnB3 ... Referer: http://localhost:8081/ ... """) HTTP/1.1 200 OK Content-Length: 89 Content-Type: text/html;charset=utf-8 ... ''' class FunctionalHTTPDocTest(unittest.TestCase): def test_dochttp(self): import sys old = sys.stdout sys.stdout = StringIO.StringIO() dochttp(['-p', 'test', directory]) got = sys.stdout.getvalue() sys.stdout = old self.assertEquals(expected, got) class AuthHeaderTestCase(unittest.TestCase): def test_auth_encoded(self): auth_header = functional.auth_header header = 'Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3' self.assertEquals(auth_header(header), header) def test_auth_non_encoded(self): auth_header = functional.auth_header header = 'Basic globalmgr:globalmgrpw' expected = 'Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3' self.assertEquals(auth_header(header), expected) def test_auth_non_encoded_empty(self): auth_header = functional.auth_header header = 'Basic globalmgr:' expected = 'Basic Z2xvYmFsbWdyOg==' self.assertEquals(auth_header(header), expected) header = 'Basic :pass' expected = 'Basic OnBhc3M=' self.assertEquals(auth_header(header), expected) def test_auth_non_encoded_colon(self): auth_header = zope.app.testing.functional.auth_header header = 'Basic globalmgr:pass:pass' expected = 'Basic Z2xvYmFsbWdyOnBhc3M6cGFzcw==' self.assertEquals(auth_header(header), expected) class HTTPCallerTestCase(unittest.TestCase): def test_chooseRequestClass(self): from zope.publisher.interfaces import IRequest, IPublication factoryRegistry.register('GET', '*', 'browser', 0, BrowserFactory()) caller = functional.HTTPCaller() request_class, publication_class = caller.chooseRequestClass( method='GET', path='/', environment={}) self.assert_(IRequest.implementedBy(request_class)) self.assert_(IPublication.implementedBy(publication_class)) class DummyCookiesResponse(object): # Ugh, this simulates the *internals* of a HTTPResponse object # TODO: expand the IHTTPResponse interface to give access to all cookies _cookies = None def __init__(self, cookies=None): if not cookies: cookies = {} self._cookies = cookies class CookieHandlerTestCase(unittest.TestCase): def setUp(self): self.handler = functional.CookieHandler() def test_saveCookies(self): response = DummyCookiesResponse(dict( spam=dict(value='eggs', path='/foo', comment='rest is ignored'), monty=dict(value='python'))) self.handler.saveCookies(response) self.assertEqual(len(self.handler.cookies), 2) self.assert_(self.handler.cookies['spam'].OutputString() in ('spam=eggs; Path=/foo;', 'spam=eggs; Path=/foo')) self.assert_(self.handler.cookies['monty'].OutputString() in ('monty=python;', 'monty=python')) def test_httpCookie(self): cookies = self.handler.cookies cookies['spam'] = 'eggs' cookies['spam']['path'] = '/foo' cookies['bar'] = 'baz' cookies['bar']['path'] = '/foo/baz' cookies['monty'] = 'python' cookieHeader = self.handler.httpCookie('/foo/bar') parts = cookieHeader.split('; ') parts.sort() self.assertEqual(parts, ['monty=python', 'spam=eggs']) cookieHeader = self.handler.httpCookie('/foo/baz') parts = cookieHeader.split('; ') parts.sort() self.assertEqual(parts, ['bar=baz', 'monty=python', 'spam=eggs']) # There is no test for CookieHandler.loadCookies because it that method # only passes the arguments on to Cookie.BaseCookie.load, which the # standard library has tests for (we hope). class HTTPFunctionalTest(HTTPTestCase): def testNoDefaultReferer(self): # There should be no referer set in the request by default. r = self.makeRequest() self.assertRaises(KeyError, r.environment.__getitem__, 'HTTP_REFERER') class BrowserFunctionalTest(BrowserTestCase): def testNoDefaultReferer(self): # There should be no referer set in the request by default. r = self.makeRequest() self.assertRaises(KeyError, r.environment.__getitem__, 'HTTP_REFERER') class HTTPCallerFunctionalTest(FunctionalTestCase): def testNoDefaultReferer(self): # There should be no referer set in the request by default. from zope.app.testing.functional import HTTPCaller http = HTTPCaller() response = http("GET /++skin++Basic HTTP/1.1\n\n") self.assertRaises(KeyError, response._request.environment.__getitem__, 'HTTP_REFERER') def testRemoteAddr(self): # There should be a REMOTE_ADDR in the request by default. from zope.app.testing.functional import HTTPCaller http = HTTPCaller() response = http("GET / HTTP/1.1\n\n") self.assertEqual(response._request.environment['REMOTE_ADDR'], '127.0.0.1') class GetCookies(object): """Get all cookies set.""" def __call__(self): cookies = ['%s=%s'%(k, v) for k, v in self.request.getCookies().items()] cookies.sort() return ';'.join(cookies) class SetCookies(object): """Set a specific cookie.""" def __call__(self): self.request.response.setCookie('bid', 'bval') class Echo(object): """Simply echo the interesting parts of the request""" def __call__(self): items = [] for k in sorted(self.request.keys()): if k in self.request.form: continue v = self.request.get(k, None) items.append('%s: %s' % (k, v)) items.extend('%s: %s' % x for x in sorted(self.request.form.items())) items.append('Body: %r' % self.request.bodyStream.read()) return '\n'.join(items) class EchoOne(object): """Echo one variable from the request""" def __call__(self): return repr(self.request.get(self.request.form['var'])) class CookieFunctionalTest(BrowserTestCase): """Functional tests should handle cookies like a web browser Multiple requests in the same test should acumulate cookies. We also ensure that cookies with path values are only sent for the correct URL's so we can test cookies don't 'leak'. Expiry, secure and other cookie attributes are not being worried about at the moment """ def setUp(self): import zope.configuration.xmlconfig super(CookieFunctionalTest, self).setUp() self.assertEqual( len(self.cookies.keys()), 0, 'cookies store should be empty') zope.configuration.xmlconfig.string(r''' ''') def testDefaultCookies(self): # By default no cookies are set response = self.publish('/') self.assertEquals(response.getStatus(), 200) self.assert_(not response._request._cookies) def testSimpleCookies(self): self.cookies['aid'] = 'aval' response = self.publish('/') self.assertEquals(response.getStatus(), 200) self.assertEquals(response._request._cookies['aid'], 'aval') def testCookiePaths(self): # We only send cookies if the path is correct self.cookies['aid'] = 'aval' self.cookies['aid']['Path'] = '/sub/folder' self.cookies['bid'] = 'bval' response = self.publish('/') self.assertEquals(response.getStatus(), 200) self.assert_('aid' not in response._request._cookies) self.assertEquals(response._request._cookies['bid'], 'bval') def testHttpCookieHeader(self): # Passing an HTTP_COOKIE header to publish adds cookies response = self.publish('/', env={ 'HTTP_COOKIE': '$Version=1, aid=aval; $Path=/sub/folder, bid=bval'}) self.assertEquals(response.getStatus(), 200) self.failIf('aid' in response._request._cookies) self.assertEquals(response._request._cookies['bid'], 'bval') def testStickyCookies(self): # Cookies should acumulate during the test response = self.publish('/', env={'HTTP_COOKIE': 'aid=aval;'}) self.assertEquals(response.getStatus(), 200) # Cookies are implicity passed to further requests in this test response = self.publish('/getcookies') self.assertEquals(response.getStatus(), 200) self.assertEquals(response.getBody().strip(), 'aid=aval') # And cookies set in responses also acumulate response = self.publish('/setcookie') self.assertEquals(response.getStatus(), 200) response = self.publish('/getcookies') self.assertEquals(response.getStatus(), 200) self.assertEquals(response.getBody().strip(), 'aid=aval;bid=bval') class SkinsAndHTTPCaller(FunctionalTestCase): def test_skins(self): # Regression test for http://zope.org/Collectors/Zope3-dev/353 from zope.app.testing.functional import HTTPCaller http = HTTPCaller() response = http("GET /++skin++Basic HTTP/1.1\n\n") self.assert_("zopetopBasic.css" in str(response)) class RetryProblemFunctional(FunctionalTestCase): def setUp(self): super(RetryProblemFunctional, self).setUp() root = self.getRootFolder() root['fail'] = FailingKlass() transaction.commit() def tearDown(self): root = self.getRootFolder() del root['fail'] super(RetryProblemFunctional, self).tearDown() def test_retryOnConflictErrorFunctional(self): from zope.app.testing.functional import HTTPCaller http = HTTPCaller() response = http(r""" GET /@@test-conflict-raise-view.html HTTP/1.1 Authorization: Basic mgr:mgrpw """) self.assertNotEqual(response.getStatus(), 599) self.assertEqual(response.getStatus(), 500) class RetryProblemBrowser(BrowserTestCase): def setUp(self): super(RetryProblemBrowser, self).setUp() root = self.getRootFolder() root['fail'] = FailingKlass() transaction.commit() def tearDown(self): root = self.getRootFolder() del root['fail'] super(RetryProblemBrowser, self).tearDown() def test_retryOnConflictErrorBrowser(self): response = self.publish('/@@test-conflict-raise-view.html', handle_errors=True) self.assertNotEqual(response.getStatus(), 599) self.assertEqual(response.getStatus(), 500) ftesting_zcml = os.path.join(here, 'ftesting.zcml') def doctest_FunctionalTestSetup_clears_global_utilities(): """Test that FunctionalTestSetup doesn't leave global utilities. Leaving global IDatabase utilities makes a nice juicy memory leak. See https://bugs.launchpad.net/zope3/+bug/251273 This bug has now been fixed and this test exercises the fixed version. >>> setup = FunctionalTestSetup(ftesting_zcml) At this point, there are registrations for the base databases created by the initialization: >>> base, = getAllUtilitiesRegisteredFor(IDatabase) Setting up for a test causes overriding registrations to be made: >>> setup.setUp() >>> dbs = list(getAllUtilitiesRegisteredFor(IDatabase)) >>> len(dbs) 1 >>> base in dbs False >>> override, = dbs Tearing down the test context causes the overriding database to be removed: >>> setup.tearDown() >>> list(getAllUtilitiesRegisteredFor(IDatabase)) [] Tearing down completely: >>> setup.tearDownCompletely() """ empty_zcml = os.path.join(here, 'empty.zcml') def doctest_FunctionalTestSetup_supports_product_config(): """Test that FunctionalTestSetup configures products. We want to apply the following product configuration before opening databases: >>> product_config = ''' ... ... key1 value1 ... key2 value2 ... ... ''' Since we expect the product configuration to be available when the layer is initialized, we'll register a subscriber for the IDatabaseOpenedEvent event, The normal CA-provided handling of the event is of no use to use, since the functional layer controls the configuration of that, but a low-level zoe.event subscriber will do the job: >>> import zope.event >>> def handle_database_open(event): ... global config ... IDbOE = zope.processlifetime.IDatabaseOpened ... if IDbOE.providedBy(event): ... config = zope.app.appsetup.product.getProductConfiguration( ... 'abc') >>> zope.event.subscribers.append(handle_database_open) The product configuration is passed to the layer setup and installed by the setUp method: >>> import pprint >>> import zope.app.appsetup.product >>> setup = FunctionalTestSetup( ... empty_zcml, product_config=product_config) The configuration was visible to our database-opened subscriber: >>> pprint.pprint(config, width=1) {'key1': 'value1', 'key2': 'value2'} >>> config = zope.app.appsetup.product.getProductConfiguration( ... 'abc') >>> pprint.pprint(config, width=1) {'key1': 'value1', 'key2': 'value2'} Let's run a test that mutates the product configuration: >>> setup.setUp() >>> zope.app.appsetup.product.setProductConfiguration( ... 'abc', {'another': 'value'}) >>> zope.app.appsetup.product.getProductConfiguration('abc') {'another': 'value'} >>> setup.tearDown() A second test run in the layer sees the original product configuration: >>> setup.setUp() >>> config = zope.app.appsetup.product.getProductConfiguration( ... 'abc') >>> pprint.pprint(config, width=1) {'key1': 'value1', 'key2': 'value2'} >>> setup.tearDown() After the layer is cleaned up, there's no longer any product configuration: >>> zope.event.subscribers.remove(handle_database_open) >>> setup.tearDownCompletely() >>> zope.app.appsetup.product.saveConfiguration() {} """ def doctest_ZCMLLayer_carries_product_configuration(): """Show that ``ZCMLLayer`` carries along product configuration. ZCML layers can carry be defined to work with specific product configuration; this is useful when application code (early subscribers, including generations) need configuration data. Let's define a couple of separate ZCML layers, and show that the configuration data is properly associated with each, and applied at appropriate times. We'll need two distinct product configurations: >>> product_config_one = ''' ... ... key1 a1 ... key2 a2 ... ... ''' >>> product_config_two = ''' ... ... key1 b1 ... key2 b2 ... ... ''' We can create two distinct layers that use these configurations: >>> LayerOne = functional.ZCMLLayer( ... empty_zcml, 'zope.app.testing.tests', 'LayerOne', ... product_config=product_config_one, ... allow_teardown=True) >>> LayerTwo = functional.ZCMLLayer( ... empty_zcml, 'zope.app.testing.tests', 'LayerTwo', ... product_config=product_config_two, ... allow_teardown=True) For each layer, we can see that the correct product configuration is installed, and subsequent layer usages won't have problems because of the previously installed layer. This checks that initialization and deconstruction of the functional test setup is handled properly to allow layers to be used in sequence. Let's use a helper function to show the configuration: >>> import pprint >>> def show_config(): ... c = zope.app.appsetup.product.getProductConfiguration('abc') ... pprint.pprint(c, width=1) >>> LayerOne.setUp() >>> show_config() {'key1': 'a1', 'key2': 'a2'} >>> LayerOne.tearDown() >>> LayerTwo.setUp() >>> show_config() {'key1': 'b1', 'key2': 'b2'} >>> LayerTwo.tearDown() """ def testbrowserSetUp(test): import zope.configuration.xmlconfig zope.configuration.xmlconfig.string(r''' ''') def test_suite(): checker = RENormalizing([ (re.compile(r'^HTTP/1.1 (\d{3}) .*?\n'), 'HTTP/1.1 \\1\n')]) SampleFunctionalTest.layer = AppTestingLayer CookieFunctionalTest.layer = AppTestingLayer SkinsAndHTTPCaller.layer = AppTestingLayer RetryProblemFunctional.layer = AppTestingLayer RetryProblemBrowser.layer = AppTestingLayer HTTPFunctionalTest.layer = AppTestingLayer BrowserFunctionalTest.layer = AppTestingLayer HTTPCallerFunctionalTest.layer = AppTestingLayer testbrowser_checker = RENormalizing([ (re.compile(r'Status: 200.*'), 'Status: 200 OK'), (re.compile(r'HTTP_USER_AGENT:\s+\S+'), 'HTTP_USER_AGENT: Python-urllib/2.4'), (re.compile(r'Content-[Ll]ength:.*'), 'Content-Length: 123'), ]) testbrowser_test = FunctionalDocFileSuite('testbrowser.txt', setUp=testbrowserSetUp, checker=testbrowser_checker) testbrowser_test.layer = AppTestingLayer doc_test = FunctionalDocFileSuite('doctest.txt', 'cookieTestOne.txt', 'cookieTestTwo.txt', checker=checker) doc_test.layer = AppTestingLayer return unittest.TestSuite(( unittest.makeSuite(FunctionalHTTPDocTest), unittest.makeSuite(AuthHeaderTestCase), unittest.makeSuite(HTTPCallerTestCase), unittest.makeSuite(CookieHandlerTestCase), DocTestSuite(), unittest.makeSuite(SampleFunctionalTest), unittest.makeSuite(HTTPFunctionalTest), unittest.makeSuite(BrowserFunctionalTest), unittest.makeSuite(HTTPCallerFunctionalTest), unittest.makeSuite(CookieFunctionalTest), unittest.makeSuite(SkinsAndHTTPCaller), unittest.makeSuite(RetryProblemFunctional), unittest.makeSuite(RetryProblemBrowser), doc_test, testbrowser_test, )) if __name__ == '__main__': unittest.main(defaultTest='test_suite') zope.app.testing-3.10.0/src/zope/app/testing/placelesssetup.py0000644000175000017500000000433611704135707022545 0ustar jimjim############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (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. # ############################################################################## """Unit test logic for setting up and tearing down basic infrastructure $Id: placelesssetup.py 110724 2010-04-11 00:04:11Z tseaver $ """ from zope.schema.vocabulary import setVocabularyRegistry from zope.component.testing import PlacelessSetup as CAPlacelessSetup from zope.component.eventtesting import PlacelessSetup as EventPlacelessSetup from zope.i18n.testing import PlacelessSetup as I18nPlacelessSetup from zope.password.testing import setUpPasswordManagers from zope.traversing.browser.interfaces import IAbsoluteURL from zope.traversing.browser.absoluteurl import AbsoluteURL from zope.app.testing import ztapi from zope.container.testing import PlacelessSetup as ContainerPlacelessSetup class PlacelessSetup(CAPlacelessSetup, EventPlacelessSetup, I18nPlacelessSetup, ContainerPlacelessSetup): def setUp(self, doctesttest=None): CAPlacelessSetup.setUp(self) EventPlacelessSetup.setUp(self) ContainerPlacelessSetup.setUp(self) I18nPlacelessSetup.setUp(self) setUpPasswordManagers() ztapi.browserView(None, 'absolute_url', AbsoluteURL) ztapi.browserViewProviding(None, AbsoluteURL, IAbsoluteURL) from zope.security.testing import addCheckerPublic addCheckerPublic() from zope.security.management import newInteraction newInteraction() setVocabularyRegistry(None) ps = PlacelessSetup() setUp = ps.setUp def tearDown(): tearDown_ = ps.tearDown def tearDown(doctesttest=None): tearDown_() return tearDown tearDown = tearDown() del ps zope.app.testing-3.10.0/src/zope.app.testing.egg-info/0000755000175000017500000000000011704136013020610 5ustar jimjimzope.app.testing-3.10.0/src/zope.app.testing.egg-info/namespace_packages.txt0000644000175000017500000000001611704136013025140 0ustar jimjimzope zope.app zope.app.testing-3.10.0/src/zope.app.testing.egg-info/dependency_links.txt0000644000175000017500000000000111704136013024656 0ustar jimjim zope.app.testing-3.10.0/src/zope.app.testing.egg-info/PKG-INFO0000644000175000017500000003321511704136013021711 0ustar jimjimMetadata-Version: 1.0 Name: zope.app.testing Version: 3.10.0 Summary: Zope Application Testing Support Home-page: http://pypi.python.org/pypi/zope.app.testing Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: This package provides testing support for Zope 3 applications. Besides providing numerous setup convenience functions, it implements a testing setup that allows the user to make calls to the publisher allowing to write functional tests. .. contents:: ================= FDocTest (How-To) ================= Steps to get started: 1. Use a clean/missing Data.fs 2. Create a manager with the name "mgr", password "mgrpw", and grant the zope.Manager role. 3. Install tcpwatch. 4. Create a temporary directory to record tcpwatch output. 5. Run tcpwatch using: tcpwatch.py -L 8081:8080 -s -r tmpdir (the ports are the listening port and forwarded-to port; the second need to match the Zope configuration) 6. In a browser, connect to the listening port and do whatever needs to be recorded. 7. Shut down tcpwatch. 8. Run the script src/zope/app/testing/dochttp.py: python2.4 src/zope/app/testing/dochttp.py tmpdir > somefile.txt 9. Edit the generated text file to add explanations and elide uninteresting portions of the output. 10. In a functional test module (usually ftests.py), import FunctionalDocFileSuite from zope.app.testing.functional and instantiate it, passing the name of the text file containing the test. ======================== DocTest Functional Tests ======================== This file documents and tests doctest-based functional tests and basic Zope web-application functionality. Request/Response Functional Tests --------------------------------- You can create Functional tests as doctests. Typically, this is done by using a script such as src/zope/app/testing/dochttp.py to convert tcpwatch recorded output to a doctest, which is then edited to provide explanation and to remove uninteresting details. That is how this file was created. Here we'll test some of the most basic types of access. First, we'll test accessing a protected page without credentials: >>> print http(r""" ... GET /@@contents.html HTTP/1.1 ... """) HTTP/1.1 401 Unauthorized Cache-Control: no-store, no-cache, must-revalidate Content-Length: ... Content-Type: text/html;charset=utf-8 Expires: Mon, 26 Jul 1997 05:00:00 GMT Pragma: no-cache WWW-Authenticate: basic realm="Zope" >> print http(r""" ... GET /@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> print http(r""" ... GET /++etc++site/@@manage HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.1 303 See Other Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@contents.html Note that, in this case, we got a 303 response. A 303 response is the prefered response for this sort of redirect with HTTP 1.1. If we used HTTP 1.0, we'd get a 302 response: >>> print http(r""" ... GET /++etc++site/@@manage HTTP/1.0 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.0 302 Moved Temporarily Content-Length: 0 Content-Type: text/plain;charset=utf-8 Location: @@contents.html Lets visit the page we were redirected to: >>> print http(r""" ... GET /++etc++site/@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Referer: http://localhost:8081/ ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> print http(r""" ... GET / HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.1 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 >> root = getRootFolder() >>> root You can intermix HTTP requests with regular Python calls. Note, however, that making an `http()` call implied a transaction commit. If you want to throw away changes made in Python code, abort the transaction before the HTTP request. >>> print http(r""" ... POST /@@contents.html HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... Content-Length: 73 ... Content-Type: application/x-www-form-urlencoded ... ... type_name=BrowserAdd__zope.site.folder.Folder&new_value=f1""", ... handle_errors=False) HTTP/1.1 303 See Other Content-Length: ... Content-Type: text/html;charset=utf-8 Location: http://localhost/@@contents.html >> list(root.keys()) [u'f1'] ======= CHANGES ======= 3.10.0 (2012-01-13) ------------------- - Removed test dependency on ``zope.app.authentication``. zope.testbrowser 4 depends on this change (seriously) if it find zope.app.testing. 3.9.0 (2011-03-14) ------------------ - Move zope.app.testing testbrowser functionality into zope.app.testing. This requires zope.testbrowser version 4.0.0 or above. 3.8.1 (2011-01-07) ------------------ - Include REMOTE_ADDR ('127.0.0.1') in the request environment. 3.8.0 (2010-09-14) ------------------ - Remove invalid HTTP_REFERER default. (We both don't want a default to allow others testing without a referer and 'localhost' is not a reasonable default anyway.) This improves the situation for #98437 - Made the xmlrpc code compatible with Python 2.7. - Removed test dependency on ``zope.app.zptpage``. - Switched test dependency from ``zope.app.securitypolicy`` to ``zope.securitypolicy``. 3.7.7 (2010-09-14) ------------------ - Rereleasing 3.7.5 as 3.7.7 to fix brown bag release. 3.7.6 (2010-09-14) ------------------ - Brown bag release: It broke the tests of ``zope.testbrowser``. 3.7.5 (2010-04-10) ------------------ - Switch doctests to use the stdlib ``doctest`` module, rather than the deprecated ``zope.testing.doctest`` variant. 3.7.4 (2010-01-08) ------------------ - Import hooks functionality from zope.component after it was moved there from zope.site. - Import ISite from zope.component after it was moved there from zope.location. This lifts the dependency on zope.location. - Fix tests using a newer zope.publisher that requires zope.login. 3.7.3 (2009-08-20) ------------------ - Fixed tests for python 2.4 as well as python 2.5 and 2.6; the change in version 3.7.1 introduced test regressions in python 2.4. 3.7.2 (2009-07-24) ------------------ - Adjusted tests after the referenced memory leak problem has been fixed in ``zope.component``. 3.7.1 (2009-07-21) ------------------ - Fixed failing tests. The code revealed that the tests expected the wrong value. 3.7.0 (2009-06-19) ------------------ - Depend on new ``zope.processlifetime`` interfaces instead of using BBB imports from ``zope.app.appsetup``. - Removed unused dependency on ``zope.app.component``. 3.6.2 (2009-04-26) ------------------ - Removed deprecated back35 module and loose the dependency on ``zope.deferredimport``. - Adapt to ``zope.app.authentication`` refactoring. We depend on ``zope.password`` now instead. - Adapt to latest ``zope.app.security`` refactoring. We don't need this package anymore. 3.6.1 (2009-03-12) ------------------ - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition for calling setDefaultSkin in HTTPCaller. This at the same time removes dependency to the browser part of zope.publisher. - Adapt to the move of IDefaultViewName from zope.component.interfaces to zope.publisher.interfaces. - Remove the DEPENDENCIES.cfg file for zpkg. 3.6.0 (2009-02-01) ------------------ - Fix AttributeError in ``zope.app.testing.setup.setUpTestAsModule`` (when called without name argument). - Use ``zope.container`` instead of ``zope.app.container``. - Use ``zope.site`` instead of ``zope.app.folder`` and ``zope.app.component`` for some parts. 3.5.6 (2008-10-13) ------------------ - Change argument variable name in provideAdapter to not conflict with buitin keyword in Python 2.6. 3.5.5 (2008-10-10) ------------------ - Re-configured functional test setup to create test-specific instances of HTTPCaller to ensure that cookies are not shared by doctests in a test suite. 3.5.4 (2008-08-25) ------------------ - Clean up some transaction management in the functional test setup. 3.5.3 (2008-08-22) ------------------ - Fix isolation enforcement for product configuration around individual tests. 3.5.2 (2008-08-21) ------------------ - Added missing dependency information in setup.py. - Added missing import. - Repair memory leak fix released in 3.4.3 to be more sane in the presence of generations. 3.5.1 (2008-08-20) ------------------ - Correct Fred's "I'm a doofus" release. 3.5.0 (2008-08-20) ------------------ - Add support for product-configuration as part of functional layers; this more closely mirrors the configuration order for normal operation. 3.4.3 (2008-07-25) ------------------ - Fix memory leak in all functional tests. see: https://bugs.launchpad.net/zope3/+bug/251273 3.4.2 (2008-02-02) ------------------ - Fix of 599 error on conflict error in request see: http://mail.zope.org/pipermail/zope-dev/2008-January/030844.html 3.4.1 (2007-10-31) ------------------ - Fixed deprecation warning for ``ZopeSecurityPolicy``. 3.4.0 (2007-10-27) ------------------ - Initial release independent of the main Zope tree. Keywords: zope3 test testing setup functional Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.app.testing-3.10.0/src/zope.app.testing.egg-info/requires.txt0000644000175000017500000000061211704136013023207 0ustar jimjimsetuptools zope.annotation zope.app.appsetup >= 3.11 zope.processlifetime zope.app.debug zope.app.dependable zope.app.publication zope.component >= 3.8 zope.container zope.i18n zope.interface zope.password zope.publisher zope.schema zope.security zope.site zope.testing zope.testbrowser >= 4 zope.traversing [test] ZODB3 zope.app.zcmlfiles zope.login zope.publisher >= 3.12 zope.securitypolicyzope.app.testing-3.10.0/src/zope.app.testing.egg-info/top_level.txt0000644000175000017500000000000511704136013023335 0ustar jimjimzope zope.app.testing-3.10.0/src/zope.app.testing.egg-info/not-zip-safe0000644000175000017500000000000111704136013023036 0ustar jimjim zope.app.testing-3.10.0/src/zope.app.testing.egg-info/SOURCES.txt0000644000175000017500000000230511704136013022474 0ustar jimjim.bzrignore CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.app.testing.egg-info/PKG-INFO src/zope.app.testing.egg-info/SOURCES.txt src/zope.app.testing.egg-info/dependency_links.txt src/zope.app.testing.egg-info/namespace_packages.txt src/zope.app.testing.egg-info/not-zip-safe src/zope.app.testing.egg-info/requires.txt src/zope.app.testing.egg-info/top_level.txt src/zope/app/__init__.py src/zope/app/testing/__init__.py src/zope/app/testing/cookieTestOne.txt src/zope/app/testing/cookieTestTwo.txt src/zope/app/testing/dochttp.py src/zope/app/testing/dochttp.txt src/zope/app/testing/doctest.txt src/zope/app/testing/empty.zcml src/zope/app/testing/ftesting.zcml src/zope/app/testing/functional.py src/zope/app/testing/placelesssetup.py src/zope/app/testing/setup.py src/zope/app/testing/testbrowser.py src/zope/app/testing/testbrowser.txt src/zope/app/testing/testing.py src/zope/app/testing/tests.py src/zope/app/testing/xmlrpc.py src/zope/app/testing/ztapi.py src/zope/app/testing/recorded/test0001.request src/zope/app/testing/recorded/test0001.response src/zope/app/testing/recorded/test0002.request src/zope/app/testing/recorded/test0002.responsezope.app.testing-3.10.0/buildout.cfg0000644000175000017500000000015211704135707015436 0ustar jimjim[buildout] develop = . parts = test [test] recipe = zc.recipe.testrunner eggs = zope.app.testing [test] zope.app.testing-3.10.0/COPYRIGHT.txt0000644000175000017500000000004011704135707015233 0ustar jimjimZope Foundation and Contributors