6

私はこれらのいくつかを行うPythonモジュール/スクリプトを持っています

  1. スクリプト内のさまざまなネストされたレベルで、コマンドライン入力を受け取り、それらを検証し、適切なデフォルトを適用します
  2. また、いくつかのディレクトリが存在するかどうかを確認します

上記はほんの2つの例です。私はこれをテストするための最良の「戦略」を見つけようとしています。私が行ったことは、モジュールの周囲raw_inputos.path.existsモジュール内にラッパー関数を作成し、テストでこれら2つの関数をオーバーライドして、配列リストから入力を取得するか、モック動作を実行することです。このアプローチには、次の欠点があります。

  1. ラッパー関数はテストのためだけに存在し、これはコードを汚染します
  2. os.path.existsまたはを呼び出すだけでなく、コードでラッパー関数を毎回使用することを忘れないでください。raw_input

素晴らしい提案はありますか?

4

3 に答える 3

3

解決策1:それが機能するので、私はこのようなことをします:

def setUp(self):
    self._os_path_exists = os.path.exists
    os.path.exists = self.myTestExists # mock

def tearDown(self):
    os.path.exists = self._os_path_exists

あまりいいことではありません。

Solution2:あなたが言ったように、コードを再構築することは選択肢ではありませんでしたね?理解が悪くなり、直感的ではなくなります。

于 2013-02-19T12:50:01.573 に答える
3

簡単な答えは、これらのシステムコールにモンキーパッチを適用することです。

Pythonでリダイレクトされたstdinを表示する方法の答えにいくつかの良い例がありますか?

これは、プロンプトを破棄して必要なものを返すをraw_input()使用する簡単な例です。lambda

テスト対象システム

$ cat ./name_getter.py
#!/usr/bin/env python

class NameGetter(object):

    def get_name(self):
        self.name = raw_input('What is your name? ')

    def greet(self):
        print 'Hello, ', self.name, '!'

    def run(self):
        self.get_name()
        self.greet()

if __name__ == '__main__':
    ng = NameGetter()
    ng.run()

$ echo Derek | ./name_getter.py 
What is your name? Hello,  Derek !

テストケース:

$ cat ./t_name_getter.py
#!/usr/bin/env python

import unittest
import name_getter

class TestNameGetter(unittest.TestCase):

    def test_get_alice(self):
        name_getter.raw_input = lambda _: 'Alice'
        ng = name_getter.NameGetter()
        ng.get_name()
        self.assertEquals(ng.name, 'Alice')

    def test_get_bob(self):
        name_getter.raw_input = lambda _: 'Bob'
        ng = name_getter.NameGetter()
        ng.get_name()
        self.assertEquals(ng.name, 'Bob')

if __name__ == '__main__':
    unittest.main()

$ ./t_name_getter.py -v
test_get_alice (__main__.TestNameGetter) ... ok
test_get_bob (__main__.TestNameGetter) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
于 2013-02-19T13:12:12.493 に答える
3

Johnnyswebはあなたがしなければならないことにスポットを当てていますが、自分でロールする代わりに、モックをインポートして使用することができます。モックはユニットテスト用に特別に設計されており、実行しようとしていることを非常に簡単に実行できます。Python3.3に組み込まれています。

たとえば、os.path.isfileを置き換え、常にTrueを返す単体テストを実行する場合:

try:
    from unittest.mock import patch
except ImportError:
    from mock import patch

class SomeTest(TestCase):

    def test_blah():
        with patch("os.path.isfile", lambda x: True):
            self.assertTrue(some_function("input"))

これにより、多くの定型コードを節約でき、非常に読みやすくなります。

supbroccess.check_outputを置き換えるなど、もう少し複雑なものが必要な場合は、単純なヘルパー関数を作成できます。

def _my_monkeypatch_function(li):
     x,y = li[0], li[1]
     if x == "Reavers":
        return "Gorram"
     if x == "Inora":
        return "Shiny!"
     if x == y:
        return "The Ballad of Jayne"

def test_monkey():
     with patch("subprocess.check_output", _my_monkeypatch_function):
            assertEquals(subprocess.check_output(["Mudder","Mudder"]),
                                                 "The Ballad of Jayne")
于 2013-12-30T20:16:26.743 に答える