2013-03-28 53 views
2

我有一個長時間運行的模擬,需要在給定時間停止模擬,並檢索並觀察一些信息,然後讓模擬繼續。我最近開始使用Test Driven Design方法,不幸的是我不知道如何單元測試放入交互式shell的應用程序。如何爲嵌入IPython Interactive Shell的Python應用程序編寫單元測試

這裏是什麼,我試圖做的基本思想:

# peekaboo.py 
from IPython import embed 
from IPython.config.loader import Config 

PAB_HEADER = 'Hello, my name is PAB. How may I help you?' 
PAB_EXIT_MESSAGE = 'Goodbye, sir.' 
PAB_PROMPT_IN_TEMPLATE = 'In [PAB \\#]: ' 
PAB_PROMPT_IN2_TEMPLATE = ' .\\D.: ' 
PAB_PROMPT_OUT_TEMPLATE = 'Out [PAB \\#]: ' 

def activate(**vars): 
    """ 
    Activate PAB 0.1 by starting an interactive shell and putting 
    the variables in the scope of the caller into the scope of this 
    method. 
    """ 
    # Add variables from caller to this scope 
    locals().update(vars) 
    cfg = None 
    try: 
     get_ipython 
    except NameError: 

     cfg = Config() 
     prompt_config = cfg.PromptManager 
     prompt_config.in_template = PAB_PROMPT_IN_TEMPLATE 
     prompt_config.in2_template = PAB_PROMPT_IN2_TEMPLATE 
     prompt_config.out_template = PAB_PROMPT_OUT_TEMPLATE 

    embed(config=cfg, header=PAB_HEADER, exit_msg=PAB_EXIT_MESSAGE) 

這裏是可以使用的peek_a_boo模塊如何一個例子:

# long_running_app.py 
import peek_a_boo 
import datetime 
import random 

start_dt = datetime.datetime(2013,1,1) 
datetimes = [start_dt + datetime.timedelta(days=i) for i in range(10)] 
dt_of_interest = datetime.datetime(2013, 1, 8) 
def long_running_process(dts): 
    """ 
    simulate long running process 
    """ 
    some_data = {} 
    for dt in dts: 
     some_data[dt] = random.random() 
     if dt.date() == dt_of_interest.date(): 
      peek_a_boo.activate(**locals()) 

    return some_data 

if __name__ == '__main__': 
    data = long_running_process(datetimes) 
    print data 

我的第一個傾向是使用模擬和修補嵌入方法,並驗證它已被調用了正確的參數,但我想知道是否有人有其他建議?

UPDATE:

所以我用鼻子我的單元測試,我試過如下:

# test_peek_a_boo.py 
import nose 
import mock 

class TestPeekABoo(object): 
    def setup(self): 
     pass 

    def teardown(self): 
     pass 

    @mock.patch('IPython.embed') 
    def test_activate(self, mock_embed): 
     """ 
     Test that the activate method calls IPython embed with the correct arguments 
     """ 
     import peek_a_boo 
     a = 'Hello' 
     b = 'World' 
     peek_a_boo.activate(**locals()) 
     mock_embed.assert_called_once_with(header=peek_a_boo.PAB_HEADER, ...) 

但是當我運行:

nosetests test_peek_a_boo.py

The進程掛起。如果我運行:

nosetests test_peek_a_boo.py -s

我可以看到我的過程中掉入交互Shell。

更新2:

我能得到上面的測試通過導入測試類的test_method內peek_a_boo運行。

這測試嵌入實際上是調用,但我想能夠測試a和b使它進入激活方法的本地範圍。

回答

3

這似乎是解決方案,我想出了作品,所以我會張貼它的解決方案。

# test_peek_a_boo.py 
import nose 
import mock 

class TestPeekABoo(object): 
    def setup(self): 
     pass 

    def teardown(self): 
     pass 

    @mock.patch('IPython.embed') 
    def test_activate(self, mock_embed): 
     """ 
     Test that the activate method calls IPython embed with the correct arguments 
     """ 
     import peek_a_boo 
     a = 'Hello' 
     b = 'World' 
     peek_a_boo.activate(**locals()) 
     mock_embed.assert_called_once_with(header=peek_a_boo.PAB_HEADER, ...) 
相關問題