2013-11-28 7 views
19

を提起されていないのは、我々はそのようななめらかを持っていると仮定しましょう:は、どのようにエラーをチェックするためにpytestを使用するには

import py, pytest 

ERROR1 = ' --- Error : value < 5! ---' 
ERROR2 = ' --- Error : value > 10! ---' 

class MyError(Exception): 
    def __init__(self, m): 
     self.m = m 

    def __str__(self): 
     return self.m 

def foo(i): 
    if i < 5: 
     raise MyError(ERROR1) 
    elif i > 10: 
     raise MyError(ERROR2) 
    return i 


# ---------------------- TESTS ------------------------- 
def test_foo1(): 
    with pytest.raises(MyError) as e: 
     foo(3) 
    assert ERROR1 in str(e) 

def test_foo2(): 
    with pytest.raises(MyError) as e: 
     foo(11) 
    assert ERROR2 in str(e) 

def test_foo3(): 
     .... 
     foo(7) 
     .... 

Q:どのように私はMyErrorが提起されていないこと、test_foo3()をテストすることができますか? )

def test_foo3(): 
    assert foo(7) == 7 

しかし、私はpytest.raises(経由でそれをテストしたい: それは私がちょうどテストすることができていることは明らかです。どこか可能ですか?たとえば :場合には、その機能「foo」がまったく返り値を持っていない、

def foo(i): 
    if i < 5: 
     raise MyError(ERROR1) 
    elif i > 10: 
     raise MyError(ERROR2) 

それは私見、この方法をテストするために意味をなすことができます。

+0

問題を探しているようですが、コード 'foo(7)'は問題ありません。正しいメッセージが得られ、すべてのpytest出力でデバッグするのが簡単になります。あなたが@Faruk( ''予期しないエラー... '')から強制した提案は、エラーについては何も言わず、あなたは固執します。それをより良くするためにできることは、 'test_foo3_works_on_integers_within_range()'のようなあなたの意図を伝えることだけです。 – dhill

答えて

36

予期しない例外が発生した場合、テストは失敗します。 foo(7)を起動するだけで、MyErrorが生成されていないことがテストされます。だから、十分でしょう次

def test_foo3(): 
    foo(7) 

あなたは本当にこのためのassert文を書きたい場合は、試すことができます:

def test_foo3(): 
    try: 
     foo(7) 
    except MyError: 
     pytest.fail("Unexpected MyError ..") 
+0

ありがとう、それは動作しますが、それはクリーンなソリューションよりも、ハックのようです。たとえば、foo(4)のテストは失敗しますが、アサーションエラーが原因ではありません。 – paraklet

+0

foo(4)のテストは、予期しない例外がスローされるため失敗します。もう1つの方法は、try catchブロックにラップして特定のメッセージで失敗することです。私は私の答えを更新します。あなたはこのような例がたくさんある場合 –

+0

、それは簡単な関数でそれを書くために役に立つかもしれません: '' ' デフnot_raises(error_class、FUNC、* argsを、** kwargsから): ... ' ' ' pytestと同様の方法で書くことができます。もしあなたがそうするなら、あなたはこのすべてに利益をもたらすPRを書くことをお勧めします。 :) (リポジトリは[bitbucket](https://bitbucket.org/hpk42/pytest)にあります)。 –

3

は私がnot_raisesがうまくいくかどうかを確認するために興味がありました。この簡単なテストは (test_notraises.py)です:

from contextlib import contextmanager 

@contextmanager 
def not_raises(ExpectedException): 
    try: 
     yield 

    except ExpectedException, err: 
     raise AssertionError(
      "Did raise exception {0} when it should not!".format(
       repr(ExpectedException) 
      ) 
     ) 

    except Exception, err: 
     raise AssertionError(
      "An unexpected exception {0} raised.".format(repr(err)) 
     ) 

def good_func(): 
    print "hello" 


def bad_func(): 
    raise ValueError("BOOM!") 


def ugly_func(): 
    raise IndexError("UNEXPECTED BOOM!") 


def test_ok(): 
    with not_raises(ValueError): 
     good_func() 


def test_bad(): 
    with not_raises(ValueError): 
     bad_func() 


def test_ugly(): 
    with not_raises(ValueError): 
     ugly_func() 

動作するようには思えません。しかし、私が実際に テストでうまくいくかどうかはわかりません。 Oisinが言及したものの上に

3

ビル..

あなたは次のように動作するシンプルなnot_raises機能を作ることができますpytestのraises:あなたが持っraisesを有することに固執する場合

from contextlib import contextmanager 

@contextmanager 
def not_raises(exception): 
    try: 
    yield 
    except exception: 
    raise pytest.fail("DID RAISE {0}".format(exception)) 

これは結構ですそれであなたのテストはより読みやすくなります。しかし本質的には、自分の行でテストしたいコードブロックを実行するだけでなく、pytestはエラーが発生するとすぐにエラーが発生します。

+0

これはpy.testに組み込まれていました。場合によってはテストをより読みやすくすることができます。特に '@ pytest.mark.parametrize'と組み合わせて使用​​します。 – Arel

関連する問題