Tornado 测试:如何在运行全部测试前重置数据库及准备数据
嗨,我来帮你搞定这个问题!在Python(包括Tornado Web服务器的测试场景)里,我们有几种靠谱的方式来实现所有测试执行前的全局前置操作,类比你熟悉的Go语言main_test.go的效果,下面分两种常用的测试方案详细说明:
unittest(Tornado测试默认基于它) Tornado的测试类(比如AsyncHTTPTestCase)本身继承自unittest.TestCase,所以可以直接用unittest的全局初始化机制:
模块级全局前置:setUpModule()
如果你的测试用例都在同一个模块里,或者希望当前模块的所有测试执行前只跑一次前置操作,可以定义setUpModule()函数——它会在整个模块的测试用例执行前自动触发一次。
示例代码:
import unittest from tornado.testing import AsyncHTTPTestCase import your_tornado_app # 导入你的Tornado应用模块 def setUpModule(): # 这里放全局前置逻辑:重置数据库、准备测试基础数据等 print("执行全局前置操作:重置测试数据库、初始化基础数据") your_tornado_app.reset_test_database() # 假设你有这个函数 your_tornado_app.prepare_test_base_data() class TestHomePage(AsyncHTTPTestCase): def get_app(self): return your_tornado_app.make_app() # 返回你的Tornado应用实例 def test_home_page_status(self): response = self.fetch('/') self.assertEqual(response.code, 200) class TestAPIEndpoint(AsyncHTTPTestCase): def get_app(self): return your_tornado_app.make_app() def test_api_data_response(self): response = self.fetch('/api/data') self.assertEqual(response.code, 200)
说明:上面的setUpModule会在TestHomePage和TestAPIEndpoint的所有测试方法执行前,只运行一次,完全符合你要的全局初始化需求。
类级前置:setUpClass()
如果你的测试用例都集中在同一个测试类里,可以用@classmethod装饰的setUpClass方法——它会在当前测试类的所有测试方法执行前触发一次。
示例代码:
import unittest from tornado.testing import AsyncHTTPTestCase import your_tornado_app class TestYourTornadoApp(AsyncHTTPTestCase): @classmethod def setUpClass(cls): # 先调用父类的setUpClass,保证Tornado测试环境初始化 super().setUpClass() # 执行当前类的前置操作 print("执行类级前置操作:重置数据库") your_tornado_app.reset_test_database() def get_app(self): return your_tornado_app.make_app() def test_home_page(self): response = self.fetch('/') self.assertEqual(response.code, 200) def test_api_post(self): response = self.fetch('/api/post', method='POST', body='{"data": "test"}') self.assertEqual(response.code, 201)
pytest(更灵活的测试框架) 如果你的项目用pytest做测试框架,那可以用会话级Fixture来实现全局前置,这个Fixture会在整个测试会话(所有模块、所有类的测试用例)执行前只跑一次,是最接近Gomain_test.go的方案。
步骤如下:
- 在你的测试目录下创建
conftest.py文件(pytest会自动识别这个文件) - 定义一个
session级别的自动Fixture:
示例代码:
import pytest from tornado.ioloop import IOLoop import your_tornado_app @pytest.fixture(scope="session", autouse=True) def global_test_setup(): # 会话级前置操作:所有测试执行前只运行一次 print("执行全局测试会话前置:重置数据库、初始化测试环境") # 如果你的初始化是异步操作(比如异步连接数据库),用IOLoop.run_sync来执行 IOLoop.current().run_sync(your_tornado_app.async_reset_database) your_tornado_app.prepare_test_data() # 如果需要测试结束后执行清理操作,可以用yield分隔前置和后置 yield # 测试会话结束后的清理操作(可选) print("执行全局测试会话清理:清理测试数据") IOLoop.current().run_sync(your_tornado_app.async_cleanup_database)
说明:scope="session"表示Fixture作用域是整个测试会话,autouse=True表示不需要在测试用例里手动调用,会自动执行。不管你有多少测试文件、测试类,这个前置逻辑只会跑一次。
如果你的前置操作是异步的(比如Tornado常用的异步数据库操作),不要直接调用异步函数,需要用Tornado的IOLoop.run_sync()来同步执行异步函数,就像上面pytest示例里的写法,或者在unittest的setUpModule里这样写:
from tornado.ioloop import IOLoop def setUpModule(): IOLoop.current().run_sync(your_tornado_app.async_reset_database)
内容的提问来源于stack exchange,提问作者Trần Kim Dự

