5

Python スクリプトに障害を挿入する適切な方法はありますか? ソースコードに次のようなものをまき散らすことは避けたい:

failure_ABC = True
failure_XYZ = True
def inject_failure_ABC():
    raise Exception('ha! a fake error')
def inject_failure_XYZ():
    # delete some critical file
    pass

# some real code
if failure_ABC:
    inject_failure_ABC()
# some more real code
if failure_XYZ:
    inject_failure_XYZ()
# even more real code

編集: 私は次のアイデアを持っています:特別に細工されたコメントとして「失敗ポイント」を挿入します。Python インタープリターの前に呼び出される単純なパーサーを作成し、実際の失敗コードを使用して実際にインストルメント化された Python スクリプトを生成します。例えば:

#!/usr/bin/parser_script_producing_actual_code_and_calls python
# some real code
# FAIL_123
if foo():
    # FAIL_ABC
    execute_some_real_code()
else:
    # FAIL_XYZ
    execute_some_other_real_code()

で始まるものFAIL_はすべてスクリプトによって障害ポイントと見なされ、構成ファイルに応じて障害が有効/無効になります。どう思いますか?

4

3 に答える 3

3

unittest.mockなどのモッキング ライブラリを使用できます。また、多くのサード パーティ製ライブラリも存在します。次に、コードで使用されるオブジェクトをモックして、例外をスローしたり、必要な方法で動作したりできます。

于 2013-01-10T10:33:37.717 に答える
3

エラー処理をテストするときの最善の方法は、テストでオーバーライドできる新しいメソッドでエラーをスローする可能性のあるコードを分離することです。

class ToTest:
    def foo(...):
        try:
            self.bar() # We want to test the error handling in foo()
        except:
            ....

    def bar(self):
        ... production code ...

テスト ケースでは、テストする例外をスローするコードで拡張ToTestおよびオーバーライドできます。bar()

編集大きなメソッドを小さなメソッドに分割することを本当に検討する必要があります。これにより、コードのテスト、理解、保守が容易になります。開発プロセスを変更する方法については、テスト駆動開発を参照してください。

「失敗のコメント」を使用するというあなたの考えについて。これは良い解決策のように見えます。小さな問題が 1 つあります。Python はバイトコードを生成するときにコメントを保持しないため、独自の Python パーサーを作成する必要があります。

したがって、これを書くために数週間を費やすか、コードをテストしやすくするために数週間を費やすことができます。

ただし、違いが 1 つあります。完全に実行しないと、パーサーは役に立たなくなります。また、費やした時間でコードが少しも改善されることはありません。ほとんどの作業は、パーサーとツールに費やされます。そのため、コードを改善し、失敗のコメントを追加し、テストを作成する必要があります。

コードをリファクタリングすると、いつでも停止できますが、これまでに費やした時間は意味があり、無駄にはなりません。コードは、最初の変更で改善され始め、改善され続けます。

複雑なツールを作成するには時間がかかり、修正または回避する必要がある独自のバグがあります。これらのどれも短期的に状況を改善するものではなく、長期的に改善するという保証はありません.

于 2013-01-10T10:27:27.983 に答える
2

ある時点でコードを停止し、インタラクティブなインタープリターにフォールバックしたい場合は、次を使用できます。

assert 1==0

ただし、これは -O を指定して python を実行しない場合にのみ機能します

編集 実際、私の最初の答えは、あなたが何をしたいのかを本当に理解せずに、すばやいことでした。申し訳ありません。

変数/関数のサフィックスではなく、パラメーターを介してパラメーター化を行うと、コードがより読みやすくなる可能性があります。何かのようなもの

failure = {"ABC": False, "XYZ":False}

#Do something, maybe set failure

def inject_failure(failure):
    if not any(failure.values()):
        return
    if failure["ABC"]:
        raise Exception('ha! a fake error')
    elif failure["XYZ"]:
        # delete some critical file
        pass

inject_failure(failure)
于 2013-01-10T10:24:16.417 に答える