2013-11-28 13 views
19

kaldırdı DEĞİLDİR kontrol etmek pytest kullanmak:nasıl böyle smth var Farz edelim ki Hata

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) 
     .... 

S: test_foo3() hiçbir MyError kaldırdı olduğunu test etmek nasıl yapabilirim? O ben sadece deneme verebilecek, açıktır:

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

ama pytest.raises yoluyla test etmek istiyorum(). Bir şey olabilir mi? Örneğin: Bir durumda, bu "fan"

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

o imho, bu şekilde test etmek mantıklı olabilir, hiç geri dönüş değeri yoktur.

+0

Sorun arama gibi görünüyor, 'foo (7)' kod testi gayet iyi. Doğru mesajı alacaksınız ve tüm pytest çıktılarıyla hata ayıklamak daha kolay olacak. @Faruk ('Beklenmeyen hata ...' ') 'dan zorladığınız öneri, hata hakkında hiçbir şey söylemiyor ve takılıp kalacaksınız. Bunu daha iyi yapmak için yapabileceğiniz tek şey, 'test_foo3_works_on_integers_within_range() 'gibi niyetinizi belirtmektir. – dhill

cevap

36

Herhangi bir beklenmedik özel durum ortaya çıkarsa bir sınama başarısız olur. Sadece foo (7) 'yi çağırabilir ve MyError'un yükseltilmediğini test etmiş olursunuz. Yani, yeterli olacaktır şunlardır:

def test_foo3(): 
    foo(7) 

gerçekten bunun için bir assert ifadesi yazmak istiyorsanız, deneyebilirsiniz:

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

Teşekkürler, işe yarıyor, ama temiz bir çözümden daha çok bir kesmek gibi görünüyor. Örneğin, foo (4) için test başarısız olur, ancak onaylama hatasına bağlı değildir. Foo (4) için – paraklet

+0

testi başarısız olacaktır, çünkü beklenmeyen bir istisna atacaktır. Diğer bir yöntem de onu bir try catch bloğuna sarmak ve belirli bir mesaj ile başarısız olmaktır. Cevabımı güncelleyeceğim. Bu gibi durumlarda bir sürü varsa –

+0

basit bir işlevi olduğunu yazmayı yararlı olabilir: '' ' def not_raises (error_class, fonk, * args ** kwargs): ... ' ' Ya da pytest gibi bir benzer yaklaşım yazabilirsiniz. Eğer herkese faydası olacak bir PR yazmanızı öneririm. :) (Bu havuz [bitbucket] içinde (https://bitbucket.org/hpk42/pytest)). –

3

Bir not_raises işe yarayıp yaramayacağını görmek için merak ediyordum.

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() 

İşe görünüyor: Bu hızlı bir deney (test_notraises.py) 'dir. Ancak, testinde gerçekten iyi okunduğundan emin değilim. Oisin sözü üzerine ne

3

Bina ..

Sen benzer davranan basit not_raises işlevi yapabilir pytest en raises: yaşadığınız raises sahip sopa istiyorsanız

from contextlib import contextmanager 

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

Bu gayet Bir muadili ve böylece testleriniz daha okunabilir. Ancak özünde, kendi satırında test etmek istediğiniz kod bloğunu çalıştırmaktan başka bir şeye ihtiyacınız yoktur - bu blok bir hata ortaya çıkardığında, pytest yine de başarısız olur.

+0

Bunun keşke py.test içinde yapılmasını isterdim; Bazı durumlarda testlerin daha okunabilir olmasını sağlar. Özellikle '@ pytest.mark.parametrize' ile bağlantılı olarak. – Arel