Add sprockets.http.testing

This commit is contained in:
Dave Shawley 2019-09-01 10:05:08 -04:00
parent 7991f99807
commit cd478d0a3d
5 changed files with 99 additions and 2 deletions

View file

@ -1,5 +1,7 @@
div.body { max-width: 85% }
div.document { width: 90% }
h1.logo {font-size:inherit}
th.field-name {hyphens: manual; -webkit-hyphens: none}
dl.class dt {padding-left: 5em; padding-right: 5em; text-indent: -5em}
dl.function dt {padding-left: 5em; padding-right: 5em; text-indent: -5em}
dl.class>dt {text-indent: -45px; padding-left: 45px}
dl.function dt {text-indent: -45px; padding-left: 45px}
div.seealso {background-color: initial; border: initial}

View file

@ -113,6 +113,17 @@ raised by the callbacks are simply logged.
.. seealso:: :attr:`~sprockets.http.app.CallbackManager.on_shutdown_callbacks`
Testing your Application
------------------------
The :class:`~sprockets.http.testing.SprocketsHttpTestCase` class makes
it simple to test sprockets.http based applications. It knows how to
call the appropriate callbacks at the appropriate time. Use this as a
base class in place of :class:`~tornado.testing.AsyncHTTPTestCase` and
modify your ``get_app`` method to set ``self.app``.
.. autoclass:: sprockets.http.testing.SprocketsHttpTestCase
:members:
Response Logging
----------------
Version 0.5.0 introduced the :mod:`sprockets.http.mixins` module with
@ -177,6 +188,7 @@ If :class:`~sprockets.mixins.mediatype.ContentMixin` is being used as well,
:meth:`~sprockets.mixins.mediatype.ContentMixin.send_response` to send the
document, otherwise it is sent as JSON.
.. autoclass:: sprockets.http.mixins.ErrorWriter
:members:

View file

@ -6,6 +6,7 @@ Release History
`Next Release`_
---------------
- Make shutdown timings configurable.
- Add :class:`sprockets.http.testing.SprocketsHttpTestCase`.
`2.0.1`_ (5 Mar 2019)
----------------------

56
sprockets/http/testing.py Normal file
View file

@ -0,0 +1,56 @@
from tornado import testing
class SprocketsHttpTestCase(testing.AsyncHTTPTestCase):
"""Test case that correctly runs a sprockets.http.app.Application.
This test case correctly starts and stops a sprockets.http Application
by calling the :meth:`~sprockets.http.app.CallbackManager.start` and
:meth:`~sprockets.http.app.CallbackManager.stop` methods during ``setUp``
and ``tearDown``.
.. attribute:: app
You are required to set this attribute in your :meth:`.get_app`
implementation.
"""
shutdown_limit = 0.25
"""Maximum number of seconds to wait for the application to shut down."""
wait_timeout = 0.05
"""Number of seconds to wait between checking for pending callbacks."""
def setUp(self):
"""Hook method for setting up the test fixture before exercising it.
The sprockets.http application is started by calling the
:meth:`~sprockets.http.app.CallbackManager.start` method after the
application is created.
"""
self.app = None
super(SprocketsHttpTestCase, self).setUp()
self.app.start(self.io_loop)
def tearDown(self):
"""Hook method for deconstructing the test fixture after exercising it.
The sprockets.http application is fully stopped by calling the
:meth:`~sprockets.http.app.CallbackManager.stop` and running the ioloop
*before* stopping the ioloop. The shutdown timing is configured using
the :attr:`.shutdown_limit` and :attr:`.wait_timeout` variables.
"""
self.app.stop(self.io_loop, self.shutdown_limit, self.wait_timeout)
self.io_loop.start()
super(SprocketsHttpTestCase, self).tearDown()
def get_app(self):
"""Override this method to create your application.
Make sure to set ``self.app`` before returning.
"""
raise NotImplementedError

View file

@ -12,6 +12,7 @@ from tornado import concurrent, httpserver, httputil, ioloop, testing, web
import sprockets.http.mixins
import sprockets.http.runner
import sprockets.http.testing
import examples
@ -616,3 +617,28 @@ class RunCommandTests(MockHelper, unittest.TestCase):
command.run()
run_function.assert_called_once_with(result_closure['result'])
class TestCaseTests(unittest.TestCase):
class FakeTest(sprockets.http.testing.SprocketsHttpTestCase):
def get_app(self):
self.app = mock.Mock()
return self.app
def runTest(self):
pass
def test_that_setup_calls_start(self):
test_case = self.FakeTest()
test_case.setUp()
test_case.app.start.assert_called_once_with(test_case.io_loop)
def test_that_teardown_calls_stop(self):
test_case = self.FakeTest()
test_case.setUp()
test_case.io_loop = mock.Mock()
test_case.tearDown()
test_case.app.stop.assert_called_once_with(
test_case.io_loop, test_case.shutdown_limit,
test_case.wait_timeout)