recomiendo encarecidamente el uso de assert_raises
y assert_raises_regexp
de nose.tools
, que duplican el comportamiento de assertRaises
y assertRaisesRegexp
de unittest.TestCase
. Estos permiten el uso de la misma funcionalidad provista por unittest.TestCase
en suites de prueba que en realidad no usan la clase unittest.TestCase
.
Encuentro que @raises
es un instrumento demasiado contundente. Aquí está el código que ilustra el problema:
from nose.tools import *
something = ["aaa", "bbb"]
def foo(x, source=None):
if source is None:
source = something
return source[x]
# This is fine
@raises(IndexError)
def test1():
foo(3)
# This is fine. The expected error does not happen because we made
# a mistake in the test or in the code. The failure indicates we made
# a mistake.
@raises(IndexError)
def test2():
foo(1)
# This passes for the wrong reasons.
@raises(IndexError)
def test3():
source = something[2] # This is the line that raises the exception.
foo(10, source) # This is not tested.
# When we use assert_raises, we can isolate the line where we expect
# the failure. This causes an error due to the exception raised in
# the first line of the function.
def test4():
source = something[2]
with assert_raises(IndexError):
foo(10, source)
test3
pases, pero no porque foo
ha planteado la excepción que esperábamos pero debido a que el código que configura los datos a utilizar por foo
falla con la misma excepción.test4
muestra cómo se puede escribir la prueba usando assert_raises
para probar realmente lo que queremos probar. El problema en la primera línea provocará que Nose informe un error y luego podremos reescribir la prueba para que esa línea pueda finalmente probar lo que intentamos probar.
@raises
no permite probar el mensaje asociado a la excepción. Cuando planteo ValueError
, solo para tomar un ejemplo, generalmente quiero plantearlo con un mensaje informativo. He aquí un ejemplo:
def bar(arg):
if arg: # This is incorrect code.
raise ValueError("arg should be higher than 3")
if arg >= 10:
raise ValueError("arg should be less than 10")
# We don't know which of the possible `raise` statements was reached.
@raises(ValueError)
def test5():
bar(10)
# Yes, we're getting an exception but with the wrong value: bug found!
def test6():
with assert_raises_regexp(ValueError, "arg should be less than 10"):
bar(10)
test5
que utiliza @raises
pasará, pero pasará por la razón equivocada. test6
realiza una prueba más fina que revela que el ValueError
planteado no era el que queríamos.
casi un dup de http://stackoverflow.com/questions/11767938/how-to-use-noses-assert-raises – Stefano