2017-09-05 69 views
0

我想爲Tornado網絡應用程序編寫單元測試,我在如何正確測試使用選項模塊的代碼時遇到了問題。我定義了幾個選項並在應用程序的多個地方訪問它們,因此,我想在單元測試中測試不同的選項組合。龍捲風單元測試與tornado.options

包含一切

一個非常簡單的例子是:

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中給出的默認值開始),而不會相互影響測試。

回答

0

tornado.options可以以兩種方式使用:

  • 使用全局單。在此模式下,您可以在導入時間處撥打tornado.options.define,通過tornado.options.options訪問結果,並使用tornado.options模塊中的頂級函數解析命令行(或配置文件)。在這個例子中,你會刪除你的define_options()函數,並在頂層定義所有的選項。
  • 使用不同的tornado.options.OptionParser對象。在此模式下,您需要在define_options()函數中創建一個OptionParser()對象,請調用define()並解析方法,而不是options模塊, and return it so that other code accesses the values through this object instead of tornado.options.options中的函數。

注意的是,全球單身的風格是,tornado.options模塊最初設計的目的是使用(它吸引了來自谷歌的C++ gflags包的靈感)的方式。在這種風格中有一點可能有點棘手,那就是臨時更改標誌的值來進行測試。 unittest.mock包在tornado.options中使用的魔法對象有點麻煩,所以您必須使用幫助器方法mockable()