2

シミュレーションの特定の時間に停止し、いくつかの情報を取得して観察してから、シミュレーションを続行できるようにする必要がある長時間実行シミュレーションがあります。最近、テスト駆動設計手法を使い始めましたが、残念ながら、インタラクティブ シェルにドロップするアプリケーションを単体テストする方法がわかりません。

これが私がやろうとしていることの基本的な考え方です:

# 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

私の最初の傾向は、モックを使用して埋め込みメソッドにパッチを適用し、正しい引数で呼び出されたことを確認することですが、他の提案があるかどうか疑問に思っていましたか?

アップデート:

だから私は自分の単体テストに鼻を使っていて、次のことを試しました:

# 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 メソッドのローカル スコープに含まれていることをテストできるようにしたいと考えています。

4

1 に答える 1

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, ...)
于 2013-04-02T20:50:23.770 に答える