2017-08-09 7 views
0

コマンドのsubprocess.check_outputを使用するスクリプトがあります。このコマンドが失敗して、subprocess.CalledProcessErrorが発生する場合があります。サブプロセスの単位テスト方法.CalledProcessError

この関数の単体テスト(pytestを使用してテストを実行)を作成し、例外条件をテストしようとしています。

pytest 3.1.2

のPython 3.5.3は、私は無駄にして探索するコードのこの小さなビットを書きました。 python mytest.pyで実行すると

# mytest.py 
import subprocess 

def test_sub(): 
    try: 
     command_output = subprocess.check_output("unzip x".split()) 
     # unzip x is used to raise the exception when running with python 
     # but would be replaced by proper command that may fail 
     output = command_output 
    except subprocess.CalledProcessError as cpe: 
    #except Exception as cpe: 
     print("\nType of error:", type(cpe)) 
     print(cpe.args) 
     output = "unzip" 
    return output 

if __name__ == '__main__': 
    print(test_sub()) 

が出力さunzipコマンドが失敗し、エラーが発生しますので、予想通りunzipです。

この機能をテストするためのコード

# test.py 
import unittest 
import unittest.mock as mock 
from mytest import test_sub 
import subprocess 

class SubErrorTest(unittest.TestCase): 

    @mock.patch('mytest.subprocess', autospec=True) 
    def test_subprocess_error_thrown(self, mock_subprocess): 

     mock_subprocess.check_output.side_effect = subprocess.CalledProcessError(returncode=2,cmd=["bad"]) 
     output = test_sub() 
     self.assertEqual("unzip", output) 

実行するとpytest test.pyはテストがエラー

output = test_sub() #error thrown from here in test 

test.py:

def test_sub(): 
    try: 
     command_output = subprocess.check_output("unzip x".split()) 
     output = command_output 
except subprocess.CalledProcessError as cpe: #error is indicated here 

E TypeError: catching classes that do not inherit from BaseException is not allowed

で失敗し、私はexcept subprocess.CalledProcessError as cpe:とのコメントを解除#except Exception as cpe:コメントした場合、テストはouptutに渡しです:

test.py
Type of error: <class 'subprocess.CalledProcessError'>
()

これはsugのようですmockに指定されているようにエラーがスローされ、キャッチされ、例外ブロックが実行されることを私に知らせてください。問題は、なぜ、それがsubprocess.CalledProcessErrorをキャッチするときに機能しないのですか?

これは私が全体のプロセスで行方不明です何かがあることを推測しています。この時点でTrue

isinstance(subprocess.CalledProcessError(returncode=2,cmd=["bad"]), BaseException) 

を返します。

私には何が欠けていますか?

答えて

1

あなたは間違った経路にパッチを当てていると思います。

@mock.patch('mytest.subprocess', autospec=True) 

パスは、テスト自体ではなく、テスト中のモジュールへのパスでなければなりません。私が考えているのは、test.py名前空間のサブプロセスを模倣していることです。つまり、side_effectをsubprocess.CalledProcessErrorに設定すると、それを模擬に設定します。 side_effectを設定した後にロギングすることでこれを確認できます。

関連する問題