2009-08-13 10 views
19

estoy tratando de ejecutar esta prueba: self.assertRaises(AttributeError, branch[0].childrennodes) y branch[0] no tiene un atributo childrennodes, por lo que se debe lanzar una AttributeError, que la assertRaises debe coger, pero cuando ejecuto la prueba, la prueba falla, ya que es lanzando un AttributeError.¿Por qué assertRaises no detecta mi error de atributo al usar python unittest?

Traceback (most recent call last): 
    File "/home/tttt/../tttt/tests.py", line 504, in test_get_categories_branch 
    self.assertRaises(AttributeError, branch[0].children_nodes) 
AttributeError: 'Category' object has no attribute 'children_nodes' 

¿Alguna idea?

Respuesta

19

Creo que es porque afirma plantea solo acepta un invocable. Se evalúa para ver si el invocable genera una excepción, no si la declaración sí lo hace.

self.assertRaises(AttributeError, getattr, branch[0], "childrennodes") 

debería funcionar.

EDIT:

Como THC4k dice correctamente que recoge las declaraciones en el tiempo de recolección y error, entonces, no en tiempo de la prueba.

También esta es una razón por la que me gusta la nariz, tiene un decorador (plantea) que es útil y más claro para este tipo de pruebas.

@raises(AttributeError) 
def test_1(self) 
    branch[0].childrennodes 
+2

Esa es la solución correcta, pero la excepción ocurre cuando Python recopila los argumentos a 'self.assertRaises'. Tiene que evaluar 'branch [0] .childrennodes' antes de llamar a la función, lo que genera una excepción tal como se esperaba. –

+0

unittest tiene características similares también. Los describí en mi propia respuesta. ¡Abrazos! –

48

Cuando se ejecuta la prueba, antes de llamar a self.assertRaises, Python tiene que encontrar el valor de todos los argumentos del método. Al hacerlo, evalúa branch[0].children_nodes, lo que aumenta AttributeError. Como aún no hemos invocado assertRaises, esta excepción no se detecta, lo que hace que la prueba falle.

La solución es envolver branch[0].children_nodes en una función o una lambda:

self.assertRaises(AttributeError, lambda: branch[0].children_nodes) 

assertRaises también se pueden utilizar como un gestor de contexto (Desde Python 2.7, o en PyPI paquete 'unittest2'):

with self.assertRaises(AttributeError): 
    branch[0].children_nodes 
    # etc 

Esto es bueno porque se puede usar en bloques de código arbitrarios en el medio de una prueba, en lugar de tener que crear una nueva función solo para definir el bloque de código al que se aplica.

Se le puede dar acceso a la excepción planteada para su procesamiento posterior, si es necesario:

with self.assertRaises(AttributeError) as cm: 
    branch[0].children_nodes 

self.assertEquals(cm.exception.special_attribute, 123) 
+3

La lambda es súper elegante, gracias por publicar esto :) –

1

PYtest también tiene un decorador similar:

from pytest import raises 

def test_raising(): 
    with raises(AttributeError): 
     branch[0].childrennodes 
Cuestiones relacionadas