Skip to main content

tornado.testing —单元测试支持异步代码

支持自动测试类。

  • AsyncTestCaseAsyncHTTPTestCase:unittest.TestCase的子类,额外支持测试异步(基于 IOLoop)代码。

  • ExpectLogLogTrapTestCase:使测试日志较少垃圾。

  • main():一个简单的测试运行器(wrapper around unittest.main()),支持tornado.autoreload模块在代码更改时重新运行测试。

异步测试用例

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

TestCase 子类,用于测试基于 IOLoop 的异步代码。

unittest框架是同步的,因此测试必须在测试方法返回时完成。这意味着异步代码不能像通常一样使用。要编写使用与 tornado.gen 模块一样的基于 yield 的模式的测试函数,请使用 tornado.testing.gen_test 代替 tornado.gen.coroutine 来装饰测试方法。这个类还提供了 stop()wait() 方法用于更加手动的测试。测试方法本身必须调用 self.wait(),异步回调应该调用 self.stop() 来发送信号完成。

默认情况下,为每个测试构建一个新的 IOLoop,并且可用作 self.io_loop。此 IOLoop 应用于构建HTTP客户端/服务器等。如果正在测试的代码需要全局 IOLoop,则子类应重写 get_new_ioloop 以返回它。

IOLoopstartstop 方法不应该直接调用。相反,使用 self.stopself.wait。传递给 self.stop 的参数从 self.wait 返回。在同一测试中可以有多个 wait/stop 周期。

例:

# 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()[源代码]

为此测试创建新的 IOLoop。可以在需要特定 IOLoop (通常是单例 IOLoop.instance())的测试的子类中重写。

stop(_arg=None, **kwargs)[源代码]

停止 IOLoop,导致对 wait() 的一个未决(或未来)调用返回。

关键字参数或传递给 stop() 的单个位置参数被保存,wait() 将返回。

wait(condition=None, timeout=None)[源代码]

运行 IOLoop,直到调用停止或超时。

在超时的情况下,将抛出异常。默认超时为5秒;它可以使用 timeout 关键字参数或使用 ASYNC_TEST_TIMEOUT 环境变量全局覆盖。

如果 condition 不是None,IOLoop 将在 stop() 之后重新启动,直到 condition() 返回true。

在 3.1 版更改: 添加了 ASYNC_TEST_TIMEOUT 环境变量。

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

启动HTTP服务器的测试用例。

子类必须重写 get_app(),它返回要测试的 tornado.web.Application (或其他 HTTPServer 回调)。测试通常使用提供的 self.http_client 从此服务器提取URL。

示例,假设用户指南中的“Hello,world”示例在 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')

self.fetch() 的呼唤相当于

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

它说明了AsyncTestCase如何将异步操作(如 http_client.fetch())转换为同步操作。如果你需要在测试中进行其他异步操作,你可能需要自己使用 stop()wait()

fetch(path, **kwargs)[源代码]

方便同步抓取网址的方法。

给定的路径将附加到本地服务器的主机和端口。任何额外的kwargs将直接传递到 AsyncHTTPClient.fetch (因此可以用于通过 method="POST"body="..." 等)。

get_app()[源代码]

应该被子类覆盖以返回 tornado.web.Application 或其他 HTTPServer 回调。

get_http_port()[源代码]

返回服务器使用的端口。

为每个测试选择一个新的端口。

get_httpserver_options()[源代码]

可能被子类覆盖以返回服务器的其他关键字参数。

get_url(path)[源代码]

返回测试服务器上给定路径的绝对URL。

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

启动HTTPS服务器的测试用例。

接口一般与 AsyncHTTPTestCase 相同。

get_ssl_options()[源代码]

可能被子类覆盖以选择SSL选项。

默认情况下包括自签名测试证书。

tornado.testing.gen_test(func=None, timeout=None)[源代码]

测试等效的 @gen.coroutine,适用于测试方法。

@gen.coroutine 不能用于测试,因为 IOLoop 尚未运行。 @gen_test 应用于 AsyncTestCase 亚类的测试方法。

例:

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

默认情况下,@gen_test 在5秒后超时。可以使用 ASYNC_TEST_TIMEOUT 环境变量或具有 timeout 关键字参数的每个测试覆盖全局超时:

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

3.1 新版功能: timeout 参数和 ASYNC_TEST_TIMEOUT 环境变量。

在 4.0 版更改: 包装器现在传递 *args, **kwargs,所以它可以用于带参数的函数。

控制日志输出

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

上下文管理器捕获和抑制预期的日志输出。

用于使错误条件的测试更少噪声,同时仍然留下意外的日志条目可见。 不是线程安全。

如果记录了任何异常堆栈跟踪,则属性 logged_stack 设置为true。

用法:

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

在 4.3 版更改: 添加了 logged_stack 属性。

构造ExpectLog上下文管理器。

参数:
  • logger – 要监视的记录器对象(或记录器的名称)。传递一个空字符串来观察根记录器。
  • regex – 要匹配的正则表达式。指定记录器上与此正则表达式匹配的任何日志条目都将被禁止。
  • required – 如果为true,如果在没有匹配任何日志条目的情况下达到 with 语句的结尾,则将引发exeption。
class tornado.testing.LogTrapTestCase(methodName='runTest')[源代码]

一个测试用例,如果测试通过,捕获并丢弃所有日志输出。

一些库可以产生大量的日志输出,即使测试成功,所以这个类可以有用的最小化噪音。只需使用它作为你的测试用例的基类。通过多重继承(class MyTestCase(AsyncHTTPTestCase, LogTrapTestCase):)结合AsyncTestCase是安全的,

此类假设只配置一个日志处理程序,并且它是一个 StreamHandler。这对于 logging.basicConfig 和由 tornado.options 配置的“漂亮日志记录”都是正确的。它与其他日志缓冲机制不兼容,例如由一些测试运行者提供的那些。

4.1 版后已移除: 使用unittest模块的 --buffer 选项,或 ExpectLog

创建将在执行时使用命名的测试方法的类的实例。如果实例没有具有指定名称的方法,则引发ValueError。

测试转轮

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

一个简单的测试运行器。

这个测试运行器基本上等同于来自标准库的 unittest.main,但是增加了对Tornado样式选项解析和日志格式的支持。

运行测试的最简单的方法是通过命令行:

python -m tornado.testing tornado.test.stack_context_test

有关可以指定测试的方法,请参见标准库unittest模块。

具有许多测试的项目可能希望定义一个测试脚本,如 tornado/test/runtests.py。这个脚本应该定义一个方法 all(),它返回一个测试套件,然后调用 tornado.testing.main()。注意,即使使用测试脚本,all() 测试套件也可以通过在命令行上命名单个测试来覆盖:

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

传递到 unittest.main() 的其他关键字参数。例如,使用 tornado.testing.main(verbosity=2) 在运行时显示许多测试详细信息。有关完整参数列表,请参阅 http://docs.python.org/library/unittest.html#unittest.main

帮助函数

tornado.testing.bind_unused_port(reuse_port=False)[源代码]

将服务器套接字绑定到localhost上的可用端口。

返回一个元组(套接字,端口)。

在 4.4 版更改: 始终绑定到 127.0.0.1,而不解析名称 localhost

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

返回(希望)未使用的端口号。

此函数不保证返回的端口可用,只有在单个进程中的一系列get_unused_port调用返回不同的端口。

Use 版后已移除: bind_unused_port,保证找到一个未使用的端口。

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

获取异步测试的全局超时设置。

返回float,超时时间以秒为单位。

3.1 新版功能.