Metadata-Version: 2.0
Name: gocept.httpserverlayer
Version: 3.1
Summary: HTTP server integration for testing
Home-page: https://bitbucket.org/gocept/gocept.httpserverlayer/
Author: gocept <mail@gocept.com>
Author-email: mail@gocept.com
License: ZPL 2.1
Description-Content-Type: UNKNOWN
Keywords: HTTP server Plone testing zope.testrunner layer Zope
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: Zope :: 3
Classifier: Framework :: Zope :: 4
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Testing
Requires-Dist: setuptools
Requires-Dist: plone.testing
Provides-Extra: plonetestingzope
Requires-Dist: Zope (>=4.0b1); extra == 'plonetestingzope'
Requires-Dist: plone.testing[zope] (>=7.0dev0); extra == 'plonetestingzope'
Provides-Extra: test
Requires-Dist: shoobx.junitxml; extra == 'test'
Provides-Extra: zopeappwsgi
Requires-Dist: zope.app.wsgi (>=4); extra == 'zopeappwsgi'

======================
gocept.httpserverlayer
======================

This package provides an HTTP server for testing your application with normal
HTTP clients (e.g. a real browser). This is done using `test layers`_, which
are a feature of `zope.testrunner`_.

gocept.httpserverlayer uses `plone.testing`_ for the test layer implementation,
and exposes the following resources (accessible in your test case as
``self.layer[RESOURCE_NAME]``):

:http_host: The hostname of the HTTP server (Default: localhost)
:http_port: The port of the HTTP server (Default: 0, which means chosen
            automatically by the operating system)
:http_address: ``hostname:port``, convenient to use in URLs
   (e.g. ``'http://user:password@%s/path' % self.layer['http_address']``)

This package is compatible with Python version 2.7 and 3.6.

.. _`test layers`: http://pypi.python.org/pypi/plone.testing#layers
.. _`zope.testrunner`: http://pypi.python.org/pypi/zope.testrunner
.. _`plone.testing`: http://pypi.python.org/pypi/plone.testing

.. contents::


WSGI
====

This test layer takes a WSGI callable and runs it in a temporary HTTP server::

    import gocept.httpserverlayer.wsgi
    from mypackage import App
    import unittest

    HTTP_LAYER = gocept.httpserverlayer.wsgi.Layer()
    HTTP_LAYER.wsgi_app = App()

    class WSGIExample(unittest.TestCase):

        layer = HTTP_LAYER

        def test_something(self):
            r = urllib.urlopen('http://{0.layer[http_address]}/'.format(self))
            self.assertIn('Hello world', r.read())

You can also have a base layer provide the WSGI callable (in the
``wsgi_app`` resource)::


    import gocept.httpserverlayer.wsgi
    from mypackage import App
    import plone.testing

    class WSGILayer(plone.testing.Layer):

        def setUp(self):
            self['wsgi_app'] = App()

    WSGI_LAYER = WSGILayer()

    HTTP_LAYER = gocept.httpserverlayer.wsgi.Layer(
        name='HTTPLayer', bases=(WSGI_LAYER,))


Static files
============

This test layer serves up the contents of a directory::

    import gocept.httpserverlayer.static
    import pkg_resources
    import unittest

    HTTP_LAYER = gocept.httpserverlayer.static.Layer(
        pkg_resources.resource_filename('my.package.tests', 'fixtures'))

    class DirecoryExample(unittest.TestCase):

        layer = HTTP_LAYER

        def test_something(self):
            r = urllib.urlopen('http://{0.layer[http_address]}/'.format(self))
            self.assertIn('Hello world', r.read())

If you don't pass in a directory, a temporary directory will be created/removed
automatically. The directory is provided in the ``documentroot`` resource.
For convenience, a layer instance is already provided as ``STATIC_FILES``::

    import gocept.httpserverlayer.static
    import os.path
    import unittest

    HTTP_LAYER = gocept.httpserverlayer.static.STATIC_FILES

    class TemporaryExample(unittest.TestCase):

        layer = HTTP_LAYER

        def test_something(self):
            path = os.path.join(self.testlayer['documentroot'], 'index')
            with open(path, 'w') as f:
                f.write('Hello World!')
            r = urllib.urlopen(
                'http://{0.layer[http_address]}/index'.format(self))
            self.assertIn('Hello world', r.read())


Custom request handler
======================

This test layer allows you to provide your own HTTP request handler for very
fine-grained control::

    import gocept.httpserverlayer.custom
    import unittest

    class RequestHandler(gocept.httpserverlayer.custom.RequestHandler):

        response_code = 200
        response_body = ''
        posts_received = []

        def do_POST(self):
            length = int(self.headers['content-length'])
            self.posts_received.append(dict(
                path=self.path,
                data=self.rfile.read(length),
                headers=self.headers,
            ))
            self.send_response(self.response_code)
            self.end_headers()
            self.wfile.write(self.response_body)

    HTTP_LAYER = gocept.httpserverlayer.custom.Layer(RequestHandler)

    class POSTExample(unittest.TestCase):

        layer = HTTP_LAYER

        def test_something(self):
            urllib.urlopen('http://{0.layer[http_address]}/'.format(self),
                           urllib.urlencode({'foo': 'bar'}))
            self.assertEqual(
                'foo=bar',
                self.layer['request_handler'].posts_received[0]['data'])


Framework integration
=====================

gocept.httpserverlayer also provides integration with some web frameworks.
Different frameworks require different dependencies; this is handled via
setuptools extras of gocept.httpserverlayer (e.g. for Grok integration you need
to require ``gocept.httpserverlayer[zopeappwsgi]``).


Zope 3 / ZTK / Grok (zope.app.wsgi)
===================================

Requires ``gocept.httpserverlayer[zopeappwsgi]``

If your ZTK application uses ``zope.app.wsgi.testlayer`` (which is the
recommended test setup for Grok, for example), you can use
``gocept.httpserverlayer.zopeappwsgi.Layer`` to create a WSGI app that
integrates ZODB isolation, and ``gocept.httpserverlayer.wsgi.Layer`` to provide
the actual HTTP server. No special TestCase is required, ``unittest.TestCase``
is enough.

The ``zopeappwsgi.Layer`` expects to find the current ZODB in the plone.testing
resource ``zodbDB`` (which is used by ``plone.testing.zodb.EMPTY_ZODB``), or
you can inherit and override ``get_current_zodb``. Here's an example setup for
Grok (which uses ``zope.app.appsetup.testlayer.ZODBLayer``)::

    import gocept.httpserverlayer.wsgi
    import gocept.httpserverlayer.zopeappwsgi
    import unittest
    import zope.app.appsetup.testlayer

    ZODB_LAYER = zope.app.appsetup.testlayer.ZODBLayer(
        gocept.httpserverlayer.zopeappwsgi, 'testing.zcml')

    class WSGILayer(gocept.httpserverlayer.zopeappwsgi.Layer):

        defaultBases = (ZODB_LAYER,)

        def get_current_zodb(self):
            return ZODB_LAYER.db

    WSGI_LAYER = WSGILayer()

    HTTP_LAYER = gocept.httpserverlayer.wsgi.Layer(
        name='HTTPLayer', bases=(WSGI_LAYER,))

    class GrokExample(unittest.TestCase):

        layer = HTTP_LAYER

        def test(self):
            r = urllib.urlopen('http://%s/' % self.layer['http_address'])
            self.assertIn('Hello world', r.read())


Zope via WSGI
=============

If your Zope setup supports WSGI, you can use the WSGI integration instead of a
specialised Zope integration to run your tests.

You might see an exception complaining about the ``Connection`` header.
To fix this issue you can use an additional middleware around your WSGI
application: ``gocept.httpserverlayer.wsgi.FixupMiddleware``.


Zope / Plone via `plone.testing.zope`
=====================================

Requires ``gocept.httpserverlayer[plonetestingzope]``.

gocept.httpserverlayer provides a ``plone.testing.Layer`` at
``gocept.httpserverlayer.plonetestingzope.HTTP_SERVER`` that you can mix and match
with your base layers. No special TestCase is required, ``unittest.TestCase``
is enough.

.. caution:: This setup also uses the WSGI flavour instead of ZServer which
             was supported in `gocept.httpserverlayer < 3`.

For a plain Zope application this might look like this (uses
``plone.testing[zope]``)::

    import gocept.httpserverlayer.plonetestingzope
    import plone.testing
    import plone.testing.zope

    class Layer(plone.testing.Layer):

        defaultBases = (plone.testing.zope.STARTUP,)

        def setUp(self):
            zope.configuration.xmlconfig.file(
                'testing.zcml', package=mypackage,
                context=self['configurationContext'])

    ZOPE_LAYER = Layer()

    HTTP_LAYER = plone.testing.Layer(
        name='HTTPLayer',
        bases=(ZOPE_LAYER,
               gocept.httpserverlayer.plonetestingzope.HTTP_SERVER))


=================================
Developing gocept.httpserverlayer
=================================

:Author:
    `gocept <http://gocept.com/>`_ <mail@gocept.com>

:PyPI page:
    https://pypi.org/project/gocept.httpserverlayer/

:Issue tracker:
    https://bitbucket.org/gocept/gocept.httpserverlayer/issues

:Source code:
    https://bitbucket.org/gocept/gocept.httpserverlayer/

:Current change log:
    https://bitbucket.org/gocept/gocept.httpserverlayer/raw/tip/CHANGES.txt

:Run tests:
    Use tox, for info see: https://pypi.org/project/tox/


=====================================
Change log for gocept.httpserverlayer
=====================================


3.1 (2019-01-15)
================

- Create a wheel of the package.

- Add support for Python 3.7.


3.0 (2018-06-29)
================

- Add support for Python 3.6.

- Drop support for Zope 2.x

- Rename the setup.py extra `plonetestingz2` into `plonetestingzope`.

- Rename the module `.plonetestingz2` into `.plonetestingzope`.


2.2 (2016-12-02)
================

- Ensure compatibility with `setuptools >= 30.0`.


2.1 (2016-12-01)
================

- Support the upcoming Zope 4 through extras_require [plonetestingz4].

- Pin `transaction < 2.0` and `ZODB < 5.0` until `Zope2` is compatible with
  these releases. (See https://github.com/zopefoundation/Zope/issues/79)


2.0 (2016-04-12)
================

- Drop support for:

  - ``zope.app.testing`` (extras_require: [zopeapptesting])

  - ``Testing.ZopeTestCase`` (extras_require: [zope2testcase])

  - ``plone.app.testing`` (extras_require: [test_plonetestingz2])

  - ``Products.PloneTestCase`` (extras_require: [plonetestcase])

- Drop support for Python 2.6.

- Use ``tox`` as testrunner.

- Remove ``zc.buildout`` infrastructure.


1.5.3 (2015-01-09)
==================

- Don't overwrite ``self.port`` when it was 0.


1.5.2 (2014-05-22)
==================

- Silence "error 32: Broken pipe" errors in ``custom.Layer``, too.


1.5.1 (2014-02-10)
==================

- Silence "error 32: Broken pipe" errors in ``wsgi.Layer``, they just
  mean the client closed the connection prematurely, which is as
  harmless as it is normal.


1.5.0 (2013-11-07)
==================

- Make it possible to dictate the hostname for the httpserver via environment
  variable ``GOCEPT_HTTP_APP_HOST``. You will need this if you run your tests
  in a selenium grid on different machines.


1.4.1 (2013-10-01)
==================

- 1.4.0 was a brown-bag, let's try again.


1.4.0 (2013-10-01)
==================

- Make HTTP server and thread objects used by layers available as a resource.


1.3.0 (2013-07-18)
==================

- Replace dependency on ``distribute`` with ``setuptools``, since the projects have merged.


1.2.1 (2013-02-07)
==================

- Fix custom layer test tear down.


1.2 (2013-02-06)
================

- Fixed tests run on MacOS.

- Use the `server_address` instead of `server_name` of `HTTPServer` to be
  compatible with MacOS.

- Dropped compatability with Zope < 2.12.

- Removed customized `HTTPServer`, the `BaseHTTPServer.HTTPServer` does
  everything we need.


1.1 (2013-02-03)
================

- Add ``custom.Layer`` that uses a BaseHTTPServer with a custom RequestHandler,
  and ``static.Layer`` that server the contents of a directory.

- Dropped compatability with Python < 2.6.


1.0.1 (2012-12-21)
==================

- Avoid the property.setter spelling in the wsgi layer's code for Python 2.5
  compatibility.

- Conditionally require wsgiref to make the wsgi layer work with Python 2.4.

- Fixed an import in the plonetestcase layer's tests.


1.0 (2012-12-19)
================

initial release (extracted from gocept.selenium-1.0)


