tornado.testing — 用于异步代码的单元测试支持¶
用于自动化测试的支持类。
- AsyncTestCase和- AsyncHTTPTestCase: unittest.TestCase 的子类,对测试异步 (- IOLoop基于) 代码提供了额外的支持。
- ExpectLog: 使测试日志不那么冗长。
- main(): 一个简单的测试运行器 (unittest.main() 的包装器),支持 tornado.autoreload 模块在代码更改时重新运行测试。
异步测试用例¶
- class tornado.testing.AsyncTestCase(methodName: str = 'runTest')[source]¶
- TestCase子类,用于测试- IOLoop基于的异步代码。- unittest 框架是同步的,因此测试必须在测试方法返回之前完成。这意味着异步代码不能像通常那样使用,必须进行调整以适应。要使用协程编写测试,请用 - tornado.testing.gen_test而不是- tornado.gen.coroutine来装饰你的测试方法。- 此类还提供了 (已弃用) 的 - stop()和- wait()方法,用于更手动的方式进行测试。测试方法本身必须调用- self.wait(),而异步回调应该调用- self.stop()来表示完成。- 默认情况下,每个测试都会构建一个新的 - IOLoop,并且可以作为- self.io_loop使用。如果被测试的代码需要一个可重用的全局- IOLoop,子类应该覆盖- get_new_ioloop以返回它,尽管从 Tornado 6.3 开始,此方法已弃用。- IOLoop的- start和- stop方法不应该直接调用。相反,请使用- self.stop和- self.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() response = yield client.fetch("https://tornado.org.cn") # 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() client.fetch("https://tornado.org.cn/", self.stop) response = self.wait() # Test contents of response self.assertIn("FriendFeed", response.body) - get_new_ioloop() IOLoop[source]¶
- 返回用于此测试的 - IOLoop。- 默认情况下,每个测试都会创建一个新的 - IOLoop。子类可以覆盖此方法以返回- IOLoop.current(),如果在每个测试中使用新的- IOLoop不合适(例如,如果存在使用默认- IOLoop的全局单例),或者如果每个测试的事件循环是由另一个系统(例如- pytest-asyncio)提供的。- 已弃用,版本 6.3: 此方法将在 Tornado 7.0 中移除。 
 - wait(condition: Optional[Callable[[...], bool]] = None, timeout: Optional[float] = None) Any[source]¶
- 运行 - IOLoop直到调用 stop 或超时。- 超时情况下,将抛出异常。 默认超时时间为 5 秒,可以通过 - timeout关键字参数或全局环境变量- ASYNC_TEST_TIMEOUT覆盖。- 如果 - condition不为- None,则在调用- stop()后,- IOLoop将重新启动,直到- condition()返回- True。- 版本 3.1 中变更: 添加了环境变量 - ASYNC_TEST_TIMEOUT。
 
- class tornado.testing.AsyncHTTPTestCase(methodName: str = 'runTest')[source]¶
- 启动 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()。- get_app() Application[source]¶
- 应由子类覆盖,返回 - tornado.web.Application或其他- HTTPServer回调。
 - fetch(path: str, raise_error: bool = False, **kwargs: Any) HTTPResponse[source]¶
- 同步获取 URL 的便捷方法。 - 给定的路径将追加到本地服务器的主机和端口。 任何额外的关键字参数将直接传递给 - AsyncHTTPClient.fetch(因此可以用来传递- method="POST"、- body="..."等)。- 如果路径以 http:// 或 https:// 开头,它将被视为完整 URL,并将按原样获取。 - 如果 - raise_error为- True,如果响应代码不是 200,则会引发- tornado.httpclient.HTTPError。 这与- AsyncHTTPClient.fetch的- raise_error参数的行为相同,但这里默认值为- False(在- AsyncHTTPClient中为- True),因为测试经常需要处理非 200 响应代码。- 版本 5.0 中变更: 添加了对绝对 URL 的支持。 - 版本 5.1 中变更: 添加了 - raise_error参数。- 版本 5.1 中弃用: 此方法目前将任何异常转换为带有状态代码 599 的 - HTTPResponse。 在 Tornado 6.0 中,除- tornado.httpclient.HTTPError之外的错误将被直接传递,并且- raise_error=False将只抑制由于非 200 响应代码引发的错误。
 
- class tornado.testing.AsyncHTTPSTestCase(methodName: str = 'runTest')[source]¶
- 启动 HTTPS 服务器的测试用例。 - 接口与 - AsyncHTTPTestCase基本相同。
- tornado.testing.gen_test(*, timeout: Optional[float] = None) Callable[[Callable[[...], Union[Generator, Coroutine]]], Callable[[...], None]
- tornado.testing.gen_test(func: Callable[[...], Union[Generator, Coroutine]]) Callable[[...], None]
- 测试等效于 - @gen.coroutine,用于应用于测试方法。- @gen.coroutine不能用于测试,因为- IOLoop尚未运行。- @gen_test应该应用于- AsyncTestCase子类的测试方法。- 示例 - class MyTest(AsyncHTTPTestCase): @gen_test def test_something(self): response = yield self.http_client.fetch(self.get_url('/')) - 默认情况下, - @gen_test在 5 秒后超时。 超时可以通过环境变量- ASYNC_TEST_TIMEOUT全局覆盖,或通过关键字参数- timeout为每个测试覆盖- class MyTest(AsyncHTTPTestCase): @gen_test(timeout=10) def test_something_slow(self): response = yield self.http_client.fetch(self.get_url('/')) - 请注意, - @gen_test与- AsyncTestCase.stop、- AsyncTestCase.wait和- AsyncHTTPTestCase.fetch不兼容。 请使用如上所示的- yield self.http_client.fetch(self.get_url())代替。- 版本 3.1 中新增: 参数 - timeout和环境变量- ASYNC_TEST_TIMEOUT。- 版本 4.0 中更改: 包装器现在将传递 - *args, **kwargs,以便它可以用于带参数的函数。
控制日志输出¶
- class tornado.testing.ExpectLog(logger: Union[Logger, str], regex: str, required: bool = True, level: Optional[int] = None)[source]¶
- 上下文管理器用于捕获和抑制预期的日志输出。 - 有助于使错误条件测试更安静,同时仍然让意外日志条目可见。 *不线程安全*。 - 属性 - 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语句的末尾时没有匹配任何日志条目,则将引发异常。
- level – 来自 - logging模块的常量,指示预期的日志级别。 如果提供此参数,则只有此级别的日志消息将被认为匹配。 此外,提供的- logger将根据需要调整其级别(在- ExpectLog的持续时间内)以启用预期的消息。
 
 - 版本 6.1 中更改: 添加了 - level参数。- 版本 6.3 中弃用: 在 Tornado 7.0 中,默认情况下只有 - WARNING和更高的日志级别将被匹配。 要匹配- INFO和更低的级别,必须使用- level参数。 正在更改此设置以最大程度地减少- tornado.testing.main(默认情况下启用- INFO日志)与大多数其他测试运行器(包括 IDE 中的测试运行器)之间的差异,这些测试运行器默认情况下禁用了- INFO日志。
测试运行器¶
- tornado.testing.main(**kwargs: Any) None[source]¶
- 一个简单的测试运行器。 - 这个测试运行器本质上等同于标准库中的 - unittest.main,但它添加了对 Tornado 风格选项解析和日志格式的支持。使用- AsyncTestCase运行测试时,没有必要使用这个- main函数;这些测试是自包含的,可以使用任何测试运行器运行。- 运行测试的最简单方法是通过命令行 - python -m tornado.testing tornado.test.web_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.web_test - 传递给 - unittest.main()的其他关键字参数。例如,使用- tornado.testing.main(verbosity=2)在运行时显示许多测试详细信息。有关完整参数列表,请参考 https://docs.pythonlang.cn/library/unittest.html#unittest.main。- 版本 5.0 中的变化: 此函数不会自行生成任何输出;只生成由 - unittest模块生成的输出(以前它会添加一个 PASS 或 FAIL 日志消息)。