Source code for zope.pytest.setup

import os
from zope.configuration import xmlconfig, config
from zope.component.hooks import setHooks
from zope.testing.cleanup import cleanUp
from zope import component
from zope.event import notify
from zope.app.publication.zopepublication import ZopePublication
from zope.app.publication.httpfactory import HTTPPublicationRequestFactory

import zope.processlifetime

from zope.app import wsgi

from ZODB.DB import DB
from ZODB.DemoStorage import DemoStorage
import ZODB.interfaces

import transaction


[docs]def create_app(request, site_root): """Get a WSGI publisher application. Returns a :class:`zope.app.wsgi.WSGIPublisherApplication` with `site_root` stored in the root folder under the name ``test``. This function is meant to be used as setup/teardown handler deploying a `pytest_funcarg__`_ function. It sets up a ZODB_ connection to a ZODB_ DemoStorage and adds finalizers (`tear_down`-functionality for people from other testing frameworks) to shutdown the whole setup after the test session. The `request` parameter is expected to be a py.test :class:`FuncargRequest` (not an HTTP request or similar) which is generated by py.test while running tests. The :attr:`handle_errors` attribute of the returned application is set to ``False`` so that errors are handled by the server. To make use of this setup, you have to configure the environment properly before. Most notably you have to register basic components that subscribe to IDatabaseOpenedEvents, etc. This can normally be done using :func:`configure` or :func:`setup_config`. .. seealso:: `pytest_funcarg__`_ docs on pytest.org. .. _pytest_funcarg__: http://pytest.org/funcargs.html """ db = setup_db() connection = setup_connection(db) root = setup_root(connection) root['test'] = site_root wsgi_app = wsgi.WSGIPublisherApplication( db, HTTPPublicationRequestFactory, True) transaction.commit() def finalize(): teardown_root(root) teardown_connection(connection) teardown_db(db) request.addfinalizer(finalize) # turn this off to let the errors be handled by the server # this is useful for testing the server's error handling wsgi_app.handleErrors = False return wsgi_app
[docs]def configure(request, module, zcml): """Configure the environment. Performs a ZCML-driven configuration. The `request` parameter is expected to be a py.test :class:`FuncargRequest` (not an HTTP request or similar) which is generated by py.test while running tests. `module` is a Python module in which the ZCML file is looked up. `zcml` is a string containing the name of the ZCML file to parse. In many projects this configuration file for tests is called ``ftesting.zcml``. You normally run this function before calling :func:`create_app` as it registers basic components and event subscribers that become active when a ZODB_ connection is created and opened. This function is normally called in a `pytest_funcarg__`_ function which will be executed before your test. It adds cached setup and teardown code to be run before and after your session. That means the configuration setup and teardown will happen only once for a complete test run. .. seealso:: `pytest_funcarg__`_ docs on pytest.org. .. _pytest_funcarg__: http://pytest.org/funcargs.html """ def setup_function(): return setup_config(module, zcml) return request.cached_setup(setup=setup_function, teardown=teardown_config, scope='session')
[docs]def setup_config(package, zcml_file): """Setup a configuration. Execute the configuration specified by `package` and `zcml_file`. `package` is a Python package in which the `zcml_file` is looked up. `zcml_file` is a string giving the name of a ZCML_ file to parse. This is a helper function used by :func:`configure`. You normally use :func:`configure` to setup tests. The function registers the most common directives and then tries to parse the and execute the configuration as given in the ZCML_ file. Returns the resulting ZCML_ configuration. """ zcml_file = os.path.join(os.path.dirname(package.__file__), zcml_file) setHooks() context = config.ConfigurationMachine() xmlconfig.registerCommonDirectives(context) return xmlconfig.file(zcml_file, package=package, context=context, execute=True)
[docs]def teardown_config(config): """Clean up a ZCML configuration. Unregisters components registered. """ cleanUp()
[docs]def setup_db(): """Create a ZODB_ DB with a demo storage. Creates a ZODB :class:`DemoStorage`, turns it into a ZODB_ DB named ``main`` and sends a :class:`DatebaseOpened` event to inform other components. You normally have to configure the Zope Component Architechture using :func:`setup_config` or (preferably) :func:`configure` before you call this function. Returns a ZODB DB. """ name = 'main' storage = DemoStorage(name) db = DB(storage, database_name=name) db.setActivityMonitor(ZODB.ActivityMonitor.ActivityMonitor()) # DB are registered as utilities component.provideUtility(db, ZODB.interfaces.IDatabase, name) # And we send a event that our DB is available notify(zope.processlifetime.DatabaseOpened(db)) return db
[docs]def teardown_db(db): """Unregister ZODB_ DB. Unregisters the ``main`` database with the global site manager and closes the DB. """ # Need to unregister DB base = component.getGlobalSiteManager() base.unregisterUtility( db, ZODB.interfaces.IDatabase, 'main') db.close()
[docs]def setup_connection(db): """Open a connection to `db`. `db` is a ZODB_ DB as returned from :func:`setup_db`. Returns a connection to the database. """ return db.open()
[docs]def teardown_connection(connection): """Shutdown ZODB_ DB connection. `connection` is a (normally open) ZODB_ DB connection as returned by :func:`setup_connection`. Aborts any running transaction and closes the connection. """ transaction.abort() connection.close()
[docs]def setup_root(connection): """Get the application root. Returns the Zope application root from a ZODB DB connected to by `connection`. `connection` is an (already opened) connection to a ZODB_ DB. Return the application root, i.e. the object that contains the global site manager and other fundamental ZCA-related stuff. """ return connection.root()[ZopePublication.root_name]
[docs]def teardown_root(root): """Shutdown the application root. `root` is a ZODB_ DB application root. This function does actually nothing. """ pass