2011-05-23 19 views
120

Me hicieron una prueba sencilla:¿Cómo usar adecuadamente assertRaises() de testing de unidades con objetos NoneType?

def setUp(self): 

    self.testListNone = None 

def testListSlicing(self): 

    self.assertRaises(TypeError, self.testListNone[:1]) 

y estoy esperando la prueba a pasar, pero me estoy haciendo una excepción:

Traceback (most recent call last): 

    self.assertRaises(TypeError, self.testListNone[:1]) 

TypeError: 'NoneType' object is unsubscriptable 

pensé que assertRaises pasarán desde TypeError excepción será ser ¿elevado?

Respuesta

182

Si está utilizando python2.7 o superior puede utilizar la capacidad de assertRaises a ser su uso como un gestor de contexto y hacer:

with self.assertRaises(TypeError): 
    self.testListNone[:1] 

Si está utilizando python2.6 de otra manera además del que se le ha dado hasta ahora es usar unittest2 que es un puerto trasero de la nueva característica unittest para python2.6, y puede hacer que funcione usando el código anterior.

N.B: Soy un gran admirador de la nueva característica (SkipTest, prueba de descubrimiento ...) de unittest así que tengo la intención de utilizar unittest2 tanto como pueda. Aconsejo hacer lo mismo porque hay mucho más de lo que vienen con unittest en python2.6 <.

63

La forma habitual de usar assertRaises es llamar a una función:

self.assertRaises(TypeError, test_function, args) 

para probar que el test_function llamada de función (args) plantea una TypeError.

El problema con self.testListNone[:1] es que Python evalúa la expresión inmediatamente antes de llamar al método assertRaises. Toda la razón por la test_function y args se pasa como argumentos separados a self.assertRaises es permitir assertRaises para llamar test_function(args) desde el interior de un bloque try...except, permitiendo assertRaises para detectar la excepción.

Dado que usted ha definido self.testListNone = None, y se necesita una función para llamar, es posible utilizar operator.itemgetter así:

import operator 
self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1))) 

desde

operator.itemgetter(self.testListNone,slice(None,1)) 

es una manera de largo aliento de decir self.testListNone[:1] , pero que separa la función (operator.itemgetter) de los argumentos.

+2

Para una sola assertRaises, esta parece ser la mejor respuesta.Para un gran banco de pruebas basadas en excepciones (suponiendo que todas tengan el mismo tipo de excepción), con self.assertRaises (...) sería una buena opción. – user632657

+1

Sí, esta debería ser la respuesta correcta ya que realmente explica el problema. –

+1

Esta es definitivamente la respuesta correcta, lo que explica el problema. – Ismael

100

El problema es que TypeError se plantea 'antes' assertRaises se llama ya que los argumentos a assertRaises deben evaluarse antes de poder llamar al método. Tiene que pasar un lambda expresión como:

self.assertRaises(TypeError, lambda: self.testListNone[:1]) 
+1

Probablemente la mejor respuesta –

+0

Puede por favor ayudame en una pregunta relacionada? https://stackoverflow.com/questions/39909935/how-do-you-show-an-error-message-when-a-test-does-not-throw-an-expected-exceptio –

2

El fragmento completo sería similar al siguiente. Extiende la respuesta de @mouad a la afirmación en el mensaje de error (o generalmente str representación de su args), que puede ser útil.

from unittest import TestCase 


class TestNoneTypeError(TestCase): 

    def setUp(self): 
    self.testListNone = None 

    def testListSlicing(self): 
    with self.assertRaises(TypeError) as ctx: 
     self.testListNone[:1] 
    self.assertEqual("'NoneType' object is not subscriptable", str(ctx.exception)) 
Cuestiones relacionadas