🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### Navigation - [index](# "General Index") - [modules](# "Python Module Index") | - [next](# "tornado.util — General-purpose utilities") | - [previous](# "tornado.stack_context — Exception handling across asynchronous callbacks") | - [Tornado 4.4.dev1 documentation](#) » - [Utilities](#) » # `tornado.testing` — Unit testing support for asynchronous code Support classes for automated testing. - [`AsyncTestCase`](# "tornado.testing.AsyncTestCase") and [`AsyncHTTPTestCase`](# "tornado.testing.AsyncHTTPTestCase"): Subclasses of unittest.TestCasewith additional support for testing asynchronous ([`IOLoop`](# "tornado.ioloop.IOLoop") based) code. - [`ExpectLog`](# "tornado.testing.ExpectLog") and [`LogTrapTestCase`](# "tornado.testing.LogTrapTestCase"): Make test logs less spammy. - [`main()`](# "tornado.testing.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'*, ***kwargs*)[[source]](#) [`TestCase`](https://docs.python.org/3.4/library/unittest.html#unittest.TestCase "(in Python v3.4)") [https://docs.python.org/3.4/library/unittest.html#unittest.TestCase] subclass for testing [`IOLoop`](# "tornado.ioloop.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`](# "tornado.gen") module, decorate your test methodswith [`tornado.testing.gen_test`](# "tornado.testing.gen_test") instead of[`tornado.gen.coroutine`](# "tornado.gen.coroutine"). This class also provides the [`stop()`](# "tornado.testing.AsyncTestCase.stop")and [`wait()`](# "tornado.testing.AsyncTestCase.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`](# "tornado.ioloop.IOLoop") is constructed for each test and is availableas `self.io_loop`. This [`IOLoop`](# "tornado.ioloop.IOLoop") should be used in the construction ofHTTP clients/servers, etc. If the code being tested requires aglobal [`IOLoop`](# "tornado.ioloop.IOLoop"), subclasses should override [`get_new_ioloop`](# "tornado.testing.AsyncTestCase.get_new_ioloop") to return it. The [`IOLoop`](# "tornado.ioloop.IOLoop")‘s `start` and `stop` methods should not becalled directly. Instead, use [`self.stop`](# "tornado.testing.AsyncTestCase.stop") and [`self.wait`](# "tornado.testing.AsyncTestCase.wait"). Arguments passed to `self.stop` are returned from`self.wait`. It is possible to have multiple `wait`/`stop`cycles in the same test. Example: ~~~ # 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`()[[source]](#) Creates a new [`IOLoop`](# "tornado.ioloop.IOLoop") for this test. May be overridden insubclasses for tests that require a specific [`IOLoop`](# "tornado.ioloop.IOLoop") (usuallythe singleton [`IOLoop.instance()`](# "tornado.ioloop.IOLoop.instance")). `stop`(*_arg=None*, ***kwargs*)[[source]](#) Stops the [`IOLoop`](# "tornado.ioloop.IOLoop"), causing one pending (or future) call to [`wait()`](# "tornado.testing.AsyncTestCase.wait")to return. Keyword arguments or a single positional argument passed to [`stop()`](# "tornado.testing.AsyncTestCase.stop") aresaved and will be returned by [`wait()`](# "tornado.testing.AsyncTestCase.wait"). `wait`(*condition=None*, *timeout=None*)[[source]](#) Runs the [`IOLoop`](# "tornado.ioloop.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 a`timeout` keyword argument or globally with the`ASYNC_TEST_TIMEOUT` environment variable. If `condition` is not None, the [`IOLoop`](# "tornado.ioloop.IOLoop") will be restartedafter [`stop()`](# "tornado.testing.AsyncTestCase.stop") until `condition()` returns true. Changed in version 3.1: Added the `ASYNC_TEST_TIMEOUT` environment variable. *class *`tornado.testing.``AsyncHTTPTestCase`(*methodName='runTest'*, ***kwargs*)[[source]](#) A test case that starts up an HTTP server. Subclasses must override [`get_app()`](# "tornado.testing.AsyncHTTPTestCase.get_app"), which returns the[`tornado.web.Application`](# "tornado.web.Application") (or other [`HTTPServer`](# "tornado.httpserver.HTTPServer") callback) to be tested.Tests will typically use the provided `self.http_client` to fetchURLs from this server. Example, assuming the “Hello, world” example from the user guide is in`hello.py`: ~~~ 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 ~~~ 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 use`stop()` and `wait()` yourself. `get_app`()[[source]](#) Should be overridden by subclasses to return a[`tornado.web.Application`](# "tornado.web.Application") or other [`HTTPServer`](# "tornado.httpserver.HTTPServer") callback. `fetch`(*path*, ***kwargs*)[[source]](#) 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 to[`AsyncHTTPClient.fetch`](# "tornado.httpclient.AsyncHTTPClient.fetch") (and so could be used to pass`method="POST"`, `body="..."`, etc). `get_httpserver_options`()[[source]](#) May be overridden by subclasses to return additionalkeyword arguments for the server. `get_http_port`()[[source]](#) Returns the port used by the server. A new port is chosen for each test. `get_url`(*path*)[[source]](#) Returns an absolute url for the given path on the test server. *class *`tornado.testing.``AsyncHTTPSTestCase`(*methodName='runTest'*, ***kwargs*)[[source]](#) A test case that starts an HTTPS server. Interface is generally the same as [`AsyncHTTPTestCase`](# "tornado.testing.AsyncHTTPTestCase"). `get_ssl_options`()[[source]](#) 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*)[[source]](#) Testing equivalent of `@gen.coroutine`, to be applied to test methods. `@gen.coroutine` cannot be used on tests because the [`IOLoop`](# "tornado.ioloop.IOLoop") is notalready running. `@gen_test` should be applied to test methodson subclasses of [`AsyncTestCase`](# "tornado.testing.AsyncTestCase"). Example: ~~~ 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: ~~~ class MyTest(AsyncHTTPTestCase): @gen_test(timeout=10) def test_something_slow(self): response = yield gen.Task(self.fetch('/')) ~~~ New in version 3.1: The `timeout` argument and `ASYNC_TEST_TIMEOUT` environmentvariable. Changed in version 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*)[[source]](#) 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 `logged_stack` is set to true if any exceptionstack trace was logged. Usage: ~~~ with ExpectLog('tornado.application', "Uncaught exception"): error_response = self.fetch("/some_page") ~~~ Changed in version 4.3: Added the `logged_stack` attribute. Constructs an ExpectLog context manager. <table class="docutils field-list" frame="void" rules="none"><col class="field-name"/><col class="field-body"/><tbody valign="top"><tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"><li><strong>logger</strong> – Logger object (or name of logger) to watch. Passan empty string to watch the root logger.</li><li><strong>regex</strong> – Regular expression to match. Any log entries onthe specified logger that match this regex will be suppressed.</li><li><strong>required</strong> – If true, an exeption will be raised if the end ofthe <code class="docutils literal"><span class="pre">with</span></code> statement is reached without matching any log entries.</li></ul></td></tr></tbody></table> *class *`tornado.testing.``LogTrapTestCase`(*methodName='runTest'*)[[source]](#) 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`](https://docs.python.org/3.4/library/logging.handlers.html#logging.StreamHandler "(in Python v3.4)") [https://docs.python.org/3.4/library/logging.handlers.html#logging.StreamHandler]. This is true for both[`logging.basicConfig`](https://docs.python.org/3.4/library/logging.html#logging.basicConfig "(in Python v3.4)") [https://docs.python.org/3.4/library/logging.html#logging.basicConfig] and the “pretty logging” configured by[`tornado.options`](# "tornado.options"). It is not compatible with other log bufferingmechanisms, such as those provided by some test runners. Deprecated since version 4.1: Use the unittest module's `--buffer` option instead, or [`ExpectLog`](# "tornado.testing.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*)[[source]](#) A simple test runner. This test runner is essentially equivalent to [`unittest.main`](https://docs.python.org/3.4/library/unittest.html#unittest.main "(in Python v3.4)") [https://docs.python.org/3.4/library/unittest.html#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: ~~~ 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 like`tornado/test/runtests.py`. This script should define a method`all()` which returns a test suite and then call[`tornado.testing.main()`](# "tornado.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: ~~~ # 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.main](http://docs.python.org/library/unittest.html#unittest.main)for full argument list. ### Helper functions `tornado.testing.``bind_unused_port`(*reuse_port=False*)[[source]](#) Binds a server socket to an available port on localhost. Returns a tuple (socket, port). `tornado.testing.``get_unused_port`()[[source]](#) 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. Deprecated since version Use: bind_unused_port instead, which is guaranteed to find an unused port. `tornado.testing.``get_async_test_timeout`()[[source]](#) Get the global timeout setting for async tests. Returns a float, the timeout in seconds. New in version 3.1. © Copyright 2009-2016, The Tornado Authors. Created using [Sphinx](http://sphinx-doc.org/) 1.3.5.