2012-09-20 17 views
10

Tengo la siguiente comprobación de código de prueba para una excepción alzar en una función. Espero que pase la prueba, pero en su lugar se indica una falla. Aquí está el código de prueba:assertRaises falla, incluso el invocable aumenta la excepción requerida (python, unitest)

import unittest 

# define a user-defined exception 
class MyException(Exception): 
    def __str__(self): 
     return repr("ERROR: Just raised my exception!") 

# this is my main class with a method raising this exception 
class MyMainObject(object): 

    def func(self): 
     raise MyException() 

# the test class 
class TestConfig(unittest.TestCase): 

    def test_1(self): 

     other = MyMainObject() 
     self.assertRaises(MyException, other.func()) 

# calling the test 
if __name__ == '__main__':  
    unittest.main() 

Cuando other.func() se llama en la sentencia assert, MyException se eleva (se puede comprobar fácilmente). Por lo tanto, la prueba assertRaises debe pasar la prueba, como other.func() failes con MyException, PERO:

.... 
MyException: 'ERROR: Just raised my exception!' 

---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

FAILED (errors=1) 

no veo algo malo, por lo que agradecería alguna entrada en este problema.

+1

¡Debería notar que es un error, no una falla! su excepción ni siquiera fue atrapada. –

Respuesta

17

assertRaises llama a la función para usted. Al llamarlo usted mismo, la excepción se plantea antes deassertRaises puede probarlo.

cambiar el código para:

self.assertRaises(MyException, other.func) 

y que funcionará correctamente. Como alternativa, puede utilizar assertRaises como un gestor de contexto (Python 2.7 en adelante):

with self.assertRaises(MyException): 
    other.func() 

Usando assertRaises como un gestor de contexto tiene la ventaja añadida de que ahora puede recuperar la instancia de excepción y realizar más pruebas en él:

with self.assertRaises(MyException) as raises_cm: 
    other.func() 

exception = raises_cm.exception 
self.assertEqual(exception.args, ('foo', 'bar')) 
+0

Sabía que era algo bastante simple. Tal vez debería haberlo mirado otro día ... (2 minutos para esperar hasta que pueda hacer clic en el gancho) – Alex

+0

@Alex No me siento tan mal - Creo que esto es más una cuestión de unittest siendo poco intuitivo - Otros marcos de prueba trabaja como esperabas – mikemaccana

+0

Estoy usando el intérprete de python 3.3 en el IDE de pycharm.¿Qué pasa si quiero pasar argumentos a la función bajo prueba y también incluir un mensaje en caso de que no se genere el error deseado? Ejemplo - 'self.assertRaises (ValueError, person.set_age_method, -10," Error: la edad de la persona no puede ser negativa. ")' Con esto, obtengo una excepción: 'set_age_method toma 2 argumentos posicionales pero 3 fueron dados'. Cómo puedo solucionar esto ? Por cierto, los documentos para esta afirmación no te dicen claramente cómo hacerlo. https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises. ¿Qué es ** kwds? – testerjoe2

7

Debido a las reglas de los idiomas, los argumentos se evalúan antes de que se ingrese el código de la función llamada (y eso generalmente es algo bueno). Por lo tanto, assertRaises no puede detectar excepciones que ocurren durante la evaluación de argumentos. La solución alternativa (en más de una API) es que pase un llamable a métodos como assertRaises, para que puedan evaluarlo en un lugar que puedan controlar y donde puedan detectar excepciones. Si todo el argumento es una llamada a un método, la magia de los métodos encuadernados le permite indicar esto bastante elegante, sin lambda o tamaña estupidez:

self.assertRaises(MyException, other.func) # <- note, no parentheses after func 
+0

Estoy usando el intérprete de python 3.3 en el IDE de pycharm. ¿Qué pasa si quiero pasar argumentos a la función bajo prueba y también incluir un mensaje en caso de que no se genere el error deseado? Ejemplo - 'self.assertRaises (ValueError, person.set_age_method, -10," Error: la edad de la persona no puede ser negativa. ")' Con esto, obtengo una excepción: 'set_age_method toma 2 argumentos posicionales pero 3 fueron dados'. Cómo puedo solucionar esto ? Por cierto, los documentos para esta afirmación no te dicen claramente cómo hacerlo. https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises. ¿Qué es ** kwds? – testerjoe2

+1

@ testerjoe2 Todo lo que va después de la función, incluidos los argumentos de palabras clave como 'edad = -10' (esto es lo que significa' ** kwds'), se pasa al invocable. Debe crear el objeto 'ValueError' directamente, ya que su construcción no necesita retrasarse como la llamada a la función (los objetos de excepción son inofensivos si no los 'eleva'), por lo que quiere:' self.assertRaises (ValueError) ("Error: la edad de la persona no puede ser negativa"), person.set_age_ethod, -10) '. – delnan

Cuestiones relacionadas