2017-08-05 12 views
1

ファイルを読み込み、内容を操作して、内容に応じて値を返す関数をテストしています。機能testme私はmodule.pyに住んでいます。私はPython 2.7を実行しています。私は私のことができるように(主に文を使用しての繰り返し使用を防止するため、また、動的に様々なREAD_DATAを生成できるように)したいと思い、私はパッチデコレータとside_effectを使用したファイルの読み込み

しかし

import unittest 
import module 
from mock import patch, mock_open 

TestTestMe(unittest.TestCase): 
    ... 
    def test_test_me(self): 
     with patch('module.open', mock_open(read_data='1 2')) as _: 
      self.assertRaises(IndexError, module.testme, 'foo') 
     with patch('module.open', mock_open(read_data='1 2 3')) as _: 
      self.assertEquals(module.testme('foo'), 3) 

などでこれを達成することができます知っています私のread_dataを関数で定義するデコレータとして@patchを使ってください。このようなもの。私はクラスの定義とインポートを繰り返さない。

def give_contents(x): 
    if x == 'correct': 
     return mock_open(read_data='1 2 3') 
    else: 
     return mock_open(read_data='a b c') 

、その後のようなテスト機能を使用して:私はこれを回避しようとするが、そのような

TypeError: test_testme() takes exactly 1 argument (2 given) 

としてTypeErrorsに実行し続ける

@patch(module.open, side_effect=give_contents) 
def test_test_me(self): 
    self.assertEquals(module.testme('correct'), 3) 

。これは私を夢中にさせている。ガイダンスを高く評価します。私が省略したかもしれない詳細をいくつか追加したいのであれば、詳細を尋ねてください。私はそれらを提供します。

編集:要求されたとおりにテストする機能の実装。申し訳ありませんが、これを「重要ではない」として省略したのは明らかです。

def testme(filepath): 
    with open(filepath, 'r') as f: 
     line = f.readline().strip().split() 
    return int(line[2]) 
+1

あなたが私たちに与えたコードにtest_testme関数が何も含まれていないので、それについてはわかりません。しかし、使用している 'module.testme'メソッドであれば、メソッド定義の文字列パラメータを宣言するのを忘れてしまいました。あなたのフィードバックに応じて、私はこれを答えにするかもしれません。 –

+0

ここで全く嘲笑しないでください。 "ファイル"オブジェクトを引数に変換し、単体テストしていない他のコードを開いてファイルを開く方が良いかもしれません。次に、ある種の文字列IOオブジェクトをスタブとして渡すことができます。たとえ文字列IOで手に入れることができなくても、引き続き引数としてモックを渡すことができます。 (おそらく私が1つを使用してもモックで主張しないだろう) – jpmc26

+0

@Alceste_私は実装を追加しました。あなたが完全な答えを書いたなら、それは素晴らしいでしょう。 – user3274289

答えて

0

は、私は次のことを考慮します:

from io import TextIOWrapper, BytesIO 
from unittest.mock import patch, mock_open 

def open_file(filename): 
    with open(filename, 'r') as f: 
     data = f.readline() 
    return data 

def string_byte_me(input): 
    return TextIOWrapper(BytesIO(input)) 

def side_effect(filename, mode): 
    if filename == 'correct': 
     return string_byte_me(b'1 2 3') 
    else: 
     return string_byte_me(b'a b c') 

m = mock_open() 
m.side_effect = side_effect 
@patch('builtins.open', m) 
def test_open_file(): 
    assert open_file('correct') == '1 2 3' 
    assert open_file('incorrect') == 'a b c' 
test_open_file() # Passes. 

これは、インスタンス化した後mock_openオブジェクトにside_effectを追加することで機能します(より良い方法があるかどうかわかりません?)。返されるside_effectは、.readline()、つまりTextIOWrapperを使用できる必要があります。

1

以前のコメントで述べたように: あなたが私たちに与えたコードにtest_testme関数が何も含まれていないので、それについてはわかりません。ただし、使用しているmodule.testmeメソッドの場合は、メソッド定義で文字列パラメータを宣言するのを忘れてしまいました。あなたのフィードバックに応じて、私はこれを答えにするかもしれません。

編集:忘れてしまった議論がむしろ自己であったため、私はその場にいませんでした。

明らかに、これはあなたのために働いたので、ここで約束された答えです。あなたはについて話module.testme方法を想定し

は、のように見えるの関数である:

TestTestMe(unittest.TestCase): 
... 
def testme(filepath): 
with open(filepath, 'r') as f: 
    line = f.readline().strip().split() 
return int(line[2]) 

この機能を使用すると、オブジェクトからアクセスされているとして、しかし、むしろ方法です。 (module.testme('foo')を実行している)、呼び出しに与えられた最初の引数は常に暗黙のselfになります。

これは、文字列( 'foo')という1つの引数を期待する関数がありますが、selfが明示的でなくても2つ与えられます: '(self、' foo ')'。

このように、あなたが求めるより多くの引数を受け取るというエラーです。 修正は非常に簡単です:testmeの予想される引数にselfを追加してください。その後になる

def testme(self, filepath): 
    with open(filepath, 'r') as f: 
     line = f.readline().strip().split() 
    return int(line[2]) 

が、これは助けを願っています。議論の量に関する誤りは、本当にこの種の忘れられた詳細によるものです。あなたは自己を必要としませんが、それは常に最初の位置引数として(Pythonで)渡されます。

楽しい一日を! PS:いくつかの奇妙な英語のフレーズと繰り返しを申し訳ありません。

関連する問題