【问题标题】:How do you write unit tests for python applications that embed IPython Interactive Shell如何为嵌入 IPython Interactive Shell 的 Python 应用程序编写单元测试
【发布时间】:2013-03-28 21:17:39
【问题描述】:

我有一个长时间运行的模拟,我需要在模拟的给定时间停止并检索和观察一些信息,然后让模拟继续。我最近开始使用测试驱动设计方法,不幸的是我不知道如何对放入交互式 shell 的应用程序进行单元测试。

这是我想要做的基本想法:

# 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

我的第一个倾向是使用 mock 并修补 embed 方法并验证它是否已使用正确的参数调用,但我想知道是否有人有其他建议?

更新:

所以我使用鼻子进行单元测试,我尝试了以下方法:

# 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, ...)

但是当我跑步时:

鼻子测试 test_peek_a_boo.py

进程挂起。如果我跑:

鼻子测试 test_peek_a_boo.py -s

我可以看到我的进程正在进入交互式外壳。

更新 2:

我能够通过在测试类的 test_method 中导入 peek_a_boo 来运行上述测试。

这个嵌入的测试实际上是调用的,但我希望能够测试 a 和 b 是否都进入了 activate 方法的本地范围。

【问题讨论】:

    标签: python-2.7 ipython python-mock


    【解决方案1】:

    我想出的解决方案似乎可行,所以我将其作为解决方案发布。

    # 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, ...)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      • 2021-03-27
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多