【问题标题】:Tornado unittesting with tornado.options使用 tornado.options 进行 Tornado 单元测试
【发布时间】:2017-09-05 12:55:25
【问题描述】:

我正在尝试为 Tornado Web 应用程序编写单元测试,但在如何正确测试使用选项模块的代码时遇到了麻烦。我定义了几个选项并在应用程序的多个位置访问它们,因此,我想在单元测试中测试不同的选项组合。

一个包含所有内容的非常简单的示例是:

import tornado.web
from tornado.options import define, options
import tornado.ioloop


def define_options():
    define('myoption', type=str, default='MyValue')


class ExampleHandler(tornado.web.RequestHandler):
    def get(self):
        self.write({
            'myoption': options.myoption
        })


def make_app():
    ROUTES = [
        (r'/', ExampleHandler)
    ]
    return tornado.web.Application(ROUTES)


def run():
    define_options()
    app = make_app()
    app.listen(8080)
    tornado.ioloop.IOLoop.current().start()


if __name__ == '__main__':
    run()

最大的问题似乎是选项在所有正在运行的测试中都存在,我看不出我应该在哪里调用define_options 以及如何更改单个测试参数而不可能影响所有其他测试。以下面的测试代码为例:

import tornado.testing
from demo import define_options, make_app

class Test1(tornado.testing.AsyncHTTPTestCase):
    def setUp(self):
        define_options()
        super().setUp()

    def get_app(self):
        return make_app()

    def test1(self):
        response = self.fetch('/')
        print(response)

这很好用,但只要我添加第二个测试方法:

def test2(self):
    response = self.fetch('/')
    print(response)

我会收到这样的错误:

File "/Users/jan/Documents/demo/demo/demo.py", line 7, in define_options
    define('myoption', type=str, default='MyValue')
  File "/Users/jan/anaconda/envs/py3k/lib/python3.4/site-packages/tornado/options.py", line 558, in define
    callback=callback)
  File "/Users/jan/anaconda/envs/py3k/lib/python3.4/site-packages/tornado/options.py", line 228, in define
    (name, self._options[name].file_name))
tornado.options.Error: Option 'myoption' already defined in /Users/jan/Documents/demo/demo/demo.py

我可以将define_options 移动到setUpClass,但是一旦我添加了第二个测试类,我就会看到同样的问题。因此,我想知道是否有人遇到过这个问题以及我可以使用什么解决方案来运行这些测试。不仅将define_options 放在哪里,因此它只运行一次,而且我如何为不同的测试定义一组不同的选项(从define_options 中给出的默认值开始),而测试不会相互影响。

【问题讨论】:

    标签: python unit-testing tornado options


    【解决方案1】:

    tornado.options有两种使用方式:

    • 使用全局单例。在这种模式下,您调用tornado.options.define在导入时,通过tornado.options.options 访问结果,并解析命令行(或配置文件) tornado.options 模块中的顶级函数。在此示例中,您将删除 define_options() 函数并在顶层定义所有选项。
    • 使用不同的tornado.options.OptionParser 对象。 在这种模式下,您将在define_options() 函数中创建一个OptionParser() 对象,调用它的define() 并解析方法而不是@987654331 中的函数@module, and return it so that other code accesses the values through this object instead oftornado.options.options`。

    请注意,全局单例样式是 tornado.options 模块最初设计和使用的方式(它从 Google 的 C++ gflags 包中汲取灵感)。在这种风格中可能有点棘手的一件事是临时更改标志的值以进行测试。 unittest.mock 包对tornado.options 中使用的魔法对象有点麻烦,所以必须使用辅助方法mockable()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2011-11-16
      相关资源
      最近更新 更多