tornado.testing — Unit testing support for asynchronous code¶

Support classes for automated testing.

  • AsyncTestCase and AsyncHTTPTestCase: Subclasses of unittest.TestCasewith additional support for testing asynchronous (IOLoop based) code.
  • ExpectLog and LogTrapTestCase: Make test logs less spammy.
  • main(): A simple test runner (wrapper around unittest.main()) with supportfor the tornado.autoreload module to rerun the tests when code changes.

Asynchronous test cases¶

class tornado.testing.AsyncTestCase(methodName='runTest')[源代码]

TestCase subclass for testing IOLoop-basedasynchronous code.

The unittest framework is synchronous, so the test must becomplete by the time the test method returns. This means thatasynchronous code cannot be used in quite the same way as usual.To write test functions that use the same yield-based patternsused with the tornado.gen module, decorate your test methodswith tornado.testing.gen_test instead oftornado.gen.coroutine. This class also provides the stop()and wait() methods for a more manual style of testing. The testmethod itself must call self.wait(), and asynchronouscallbacks should call self.stop() to signal completion.

By default, a new IOLoop is constructed for each test and is availableas self.ioloop. This IOLoop should be used in the construction ofHTTP clients/servers, etc. If the code being tested requires aglobal IOLoop, subclasses should override get_new_ioloop to return it.

The IOLoop‘s start and stop methods should not becalled directly. Instead, use self.stop and self.wait. Arguments passed to self.stop are returned fromself.wait. It is possible to have multiple wait/stopcycles in the same test.

Example:



  1. # This test uses coroutine style.
    class MyTestCase(AsyncTestCase):
    @tornado.testing.gen_test
    def test_http_fetch(self):
    client = AsyncHTTPClient(self.io_loop)
    response = yield client.fetch("http://www.tornadoweb.org")
    # Test contents of response
    self.assertIn("FriendFeed", response.body)

    # This test uses argument passing between self.stop and self.wait.
    class MyTestCase2(AsyncTestCase):
    def test_http_fetch(self):
    client = AsyncHTTPClient(self.io_loop)
    client.fetch("http://www.tornadoweb.org/", self.stop)
    response = self.wait()
    # Test contents of response
    self.assertIn("FriendFeed", response.body)

    # This test uses an explicit callback-based style.
    class MyTestCase3(AsyncTestCase):
    def test_http_fetch(self):
    client = AsyncHTTPClient(self.io_loop)
    client.fetch("http://www.tornadoweb.org/", self.handle_fetch)
    self.wait()

    def handle_fetch(self, response):
    # Test contents of response (failures and exceptions here
    # will cause self.wait() to throw an exception and end the
    # test).
    # Exceptions thrown here are magically propagated to
    # self.wait() in test_http_fetch() via stack_context.
    self.assertIn("FriendFeed", response.body)
    self.stop()



get_new_ioloop()[源代码]

Creates a new IOLoop for this test. May be overridden insubclasses for tests that require a specific IOLoop (usuallythe singleton IOLoop.instance()).
stop(__arg=None, **kwargs)[源代码]

Stops the IOLoop, causing one pending (or future) call to wait()to return.

Keyword arguments or a single positional argument passed to stop() aresaved and will be returned by wait().
wait(condition=None, timeout=None)[源代码]

Runs the IOLoop until stop is called or timeout has passed.

In the event of a timeout, an exception will be thrown. Thedefault timeout is 5 seconds; it may be overridden with atimeout keyword argument or globally with theASYNCTEST_TIMEOUT environment variable.

If condition is not None, the IOLoop will be restartedafter stop() until condition() returns true.


在 3.1 版更改: Added the ASYNC_TEST_TIMEOUT environment variable.

_class tornado.testing.AsyncHTTPTestCase(methodName='runTest')[源代码]

A test case that starts up an HTTP server.

Subclasses must override get_app(), which returns thetornado.web.Application (or other HTTPServer callback) to be tested.Tests will typically use the provided self.httpclient to fetchURLs from this server.

Example, assuming the “Hello, world” example from the user guide is inhello.py:



  1. import hello

    class TestHelloApp(AsyncHTTPTestCase):
    def get_app(self):
    return hello.make_app()

    def test_homepage(self):
    response = self.fetch('/')
    self.assertEqual(response.code, 200)
    self.assertEqual(response.body, 'Hello, world')




That call to self.fetch() is equivalent to



  1. self.http_client.fetch(self.get_url('/'), self.stop)
    response = self.wait()




which illustrates how AsyncTestCase can turn an asynchronous operation,like http_client.fetch(), into a synchronous operation. If you needto do other asynchronous operations in tests, you’ll probably need to usestop() and wait() yourself.
fetch(_path, **kwargs)[源代码]

Convenience method to synchronously fetch a url.

The given path will be appended to the local server’s host andport. Any additional kwargs will be passed directly toAsyncHTTPClient.fetch (and so could be used to passmethod="POST", body="…", etc).
getapp()[源代码]

Should be overridden by subclasses to return atornado.web.Application or other HTTPServer callback.
get_http_port()[源代码]

Returns the port used by the server.

A new port is chosen for each test.
get_httpserver_options()[源代码]

May be overridden by subclasses to return additionalkeyword arguments for the server.
get_url(_path)[源代码]

Returns an absolute url for the given path on the test server.
class tornado.testing.AsyncHTTPSTestCase(methodName='runTest')[源代码]

A test case that starts an HTTPS server.

Interface is generally the same as AsyncHTTPTestCase.
getssl_options()[源代码]

May be overridden by subclasses to select SSL options.

By default includes a self-signed testing certificate.
tornado.testing.gen_test(_func=None, timeout=None)[源代码]

Testing equivalent of @gen.coroutine, to be applied to test methods.

@gen.coroutine cannot be used on tests because the IOLoop is notalready running. @gen_test should be applied to test methodson subclasses of AsyncTestCase.

Example:



  1. class MyTest(AsyncHTTPTestCase):
    @gen_test
    def test_something(self):
    response = yield gen.Task(self.fetch('/'))




By default, @gen_test times out after 5 seconds. The timeout may beoverridden globally with the ASYNC_TEST_TIMEOUT environment variable,or for each test with the timeout keyword argument:



  1. class MyTest(AsyncHTTPTestCase):
    @gen_test(timeout=10)
    def test_something_slow(self):
    response = yield gen.Task(self.fetch('/'))





3.1 新版功能: The timeout argument and ASYNC_TEST_TIMEOUT environmentvariable.



在 4.0 版更改: The wrapper now passes along args, *kwargs so it can be usedon functions with arguments.

Controlling log output¶

class tornado.testing.ExpectLog(logger, regex, required=True)[源代码]

Context manager to capture and suppress expected log output.

Useful to make tests of error conditions less noisy, while stillleaving unexpected log entries visible. Not thread safe.

The attribute loggedstack is set to true if any exceptionstack trace was logged.

Usage:



  1. with ExpectLog('tornado.application', "Uncaught exception"):
    error_response = self.fetch("/some_page")





在 4.3 版更改: Added the logged_stack attribute.


Constructs an ExpectLog context manager.

|参数:
|——-
|
- logger – Logger object (or name of logger) to watch. Passan empty string to watch the root logger.
- regex – Regular expression to match. Any log entries onthe specified logger that match this regex will be suppressed.
- required – If true, an exeption will be raised if the end ofthe with statement is reached without matching any log entries.

_class tornado.testing.LogTrapTestCase(methodName='runTest')[源代码]

A test case that captures and discards all logging outputif the test passes.

Some libraries can produce a lot of logging output even whenthe test succeeds, so this class can be useful to minimize the noise.Simply use it as a base class for your test case. It is safe to combinewith AsyncTestCase via multiple inheritance(class MyTestCase(AsyncHTTPTestCase, LogTrapTestCase):)

This class assumes that only one log handler is configured andthat it is a StreamHandler. This is true for bothlogging.basicConfig and the “pretty logging” configured bytornado.options. It is not compatible with other log bufferingmechanisms, such as those provided by some test runners.


4.1 版后已移除: Use the unittest module’s —buffer option instead, or ExpectLog.


Create an instance of the class that will use the named testmethod when executed. Raises a ValueError if the instance doesnot have a method with the specified name.

Test runner¶

tornado.testing.main(**kwargs)[源代码]

A simple test runner.

This test runner is essentially equivalent to unittest.main fromthe standard library, but adds support for tornado-style optionparsing and log formatting.

The easiest way to run a test is via the command line:



  1. python -m tornado.testing tornado.test.stack_context_test




See the standard library unittest module for ways in which tests canbe specified.

Projects with many tests may wish to define a test script liketornado/test/runtests.py. This script should define a methodall() which returns a test suite and then calltornado.testing.main(). Note that even when a test script isused, the all() test suite may be overridden by naming asingle test on the command line:



  1. # Runs all tests
    python -m tornado.test.runtests
    # Runs one test
    python -m tornado.test.runtests tornado.test.stack_context_test




Additional keyword arguments passed through to unittest.main().For example, use tornado.testing.main(verbosity=2)to show many test details as they are run.See http://docs.python.org/library/unittest.html#unittest.mainfor full argument list.

Helper functions¶

tornado.testing.bindunused_port(_reuse_port=False)[源代码]

Binds a server socket to an available port on localhost.

Returns a tuple (socket, port).


在 4.4 版更改: Always binds to 127.0.0.1 without resolving the namelocalhost.

tornado.testing.get_unused_port()[源代码]

Returns a (hopefully) unused port number.

This function does not guarantee that the port it returns is available,only that a series of get_unused_port calls in a single process returndistinct ports.


Use 版后已移除: bind_unused_port instead, which is guaranteed to find an unused port.

tornado.testing.get_async_test_timeout()[源代码]

Get the global timeout setting for async tests.

Returns a float, the timeout in seconds.


3.1 新版功能.

原文:

https://tornado-zh-cn.readthedocs.io/zh_CN/latest/testing.html