python - example - ¿Cómo usar adecuadamente assertRaises() de testing de unidades con objetos NoneType?
assertraises python example (4)
El fragmento completo sería similar al siguiente. Extiende la respuesta de @mouad a la afirmación en el mensaje de error (o en general representación str
de sus 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))
Esta pregunta ya tiene una respuesta aquí:
Hice un caso de prueba simple:
def setUp(self):
self.testListNone = None
def testListSlicing(self):
self.assertRaises(TypeError, self.testListNone[:1])
y estoy esperando que pase la prueba, pero estoy recibiendo una excepción:
Traceback (most recent call last):
self.assertRaises(TypeError, self.testListNone[:1])
TypeError: ''NoneType'' object is unsubscriptable
Pensé que assertRaises pasará ya que se generará la excepción TypeError.
El problema es que TypeError
se levanta ''antes'' de que se llame a assertRaises
ya que los argumentos para assertRaises
necesitan ser evaluados antes de que se pueda llamar al método. Debes pasar una expresión lambda
como:
self.assertRaises(TypeError, lambda: self.testListNone[:1])
La forma habitual de usar assertRaises
es llamar a una función:
self.assertRaises(TypeError, test_function, args)
para probar que la función llamada test_function (args) genera un TypeError.
El problema con self.testListNone[:1]
es que Python evalúa la expresión inmediatamente antes de assertRaises
método assertRaises
. La razón por la cual test_function
y args
se pasan como argumentos separados a self.assertRaises
es permitir que assertRaises
llame a test_function(args)
desde dentro de un bloque try...except
, permitiendo a assertRaises
capturar la excepción.
Como ha definido self.testListNone = None
y necesita una función para llamar, puede usar operator.itemgetter siguiente manera:
import operator
self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1)))
ya que
operator.itemgetter(self.testListNone,slice(None,1))
es una forma self.testListNone[:1]
de decir self.testListNone[:1]
, pero que separa la función ( operator.itemgetter
) de los argumentos.
Si está utilizando python2.7 o superior, puede usar la capacidad de assertRaises para usarlo como administrador de contexto y hacer:
with self.assertRaises(TypeError):
self.testListNone[:1]
Si está usando python2.6 de otra manera además del que se le ha dado hasta ahora, use 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.
NB: Soy un gran admirador de la nueva característica (SkipTest, prueba de descubrimiento ...) de unittest así que tengo la intención de usar unittest2 tanto como pueda. Aconsejo hacer lo mismo porque hay mucho más de lo que viene con unittest en python2.6 <.