miércoles, 18 de mayo de 2011

(T) 10 pruebas unitarias

unittest, también llamado PyUnit, forma parte de una familia de herramientas conocida colectivamente como xUnit, un conjunto de frameworks basados en el software SUnit para Smalltalk, creado por Kent Beck, uno de los padres de la eXtreme Programming. Otros ejemplos de herramientas que forman parte de esta familia son JUnit para Java, creada por el propio Kent Beck junto a Erich Gamma, o NUnit, para .NET.
El uso de unittest es muy sencillo. Para cada grupo de pruebas tenemos que crear una clase que herede de unittest.TestCase, y añadir una serie de métodos que comiencen con test, que serán cada una de las pruebas que queremos ejecutar dentro de esa batería de pruebas.
Para ejecutar las pruebas, basta llamar a la función main() del módulo, con lo que se ejecutarán todos los métodos cuyo nombre comience con test, en orden alfanumérico. Al ejecutar cada una de las pruebas el resultado puede ser:
  • OK: La prueba ha pasado con éxito.
  • FAIL: La prueba no ha pasado con éxito. Se lanza una excepción AssertionErrorpara indicarlo.
  • ERROR: Al ejecutar la prueba se lanzó una excepción distinta de AssertionError
En el siguiente ejemplo, dado que el método que modela nuestra prueba no lanza ninguna excepción, la prueba pasaría con éxito.
  1. import unittest  
  2.   
  3. class EjemploPruebas(unittest.TestCase):  
  4.     def test(self):  
  5.         pass  
  6.   
  7. if __name__ == "__main__":  
  8.     unittest.main()  
En este otro, sin embargo, fallaría:
  1. import unittest  
  2.   
  3. class EjemploPruebas(unittest.TestCase):  
  4.     def test(self):  
  5.         raise AssertionError()  
  6.   
  7. if __name__ == "__main__":  
  8.     unittest.main()  
Nada nos impide utilizar cláusulas if para evaluar las condiciones que nos interesen y lanzar una excepción de tipo AssertionError cuando no sea así, pero la claseTestCase cuenta con varios métodos que nos pueden facilitar la tarea de realizar comprobaciones sencillas. Son los siguientes:
  • assertAlmostEqual(first, second, places=7, msg=None): Comprueba que los objetos pasados como parámetros sean iguales hasta el séptimo decimal (o el número de decimales indicado por places).
  • assertEqual(first, second, msg=None): Comprueba que los objetos pasados como parámetros sean iguales.
  • assertFalse(expr, msg=None): Comprueba que la expresión sea falsa.
  • assertNotAlmostEqual(first, second, places=7, msg=None): Comprueba que los objetos pasados como parámetros no sean iguales hasta el séptimo decimal (o hasta el número de decimales indicado por places).
  • assertNotEqual(first, second, msg=None): Comprueba que los objetos pasados como parámetros no sean iguales.
  • assertRaises(excClass, callableObj, *args, **kwargs): Comprueba que al llamar al objeto callableObj con los parámetros definidos por *args y **kwargsse lanza una excepción de tipo excClass.
  • assertTrue(expr, msg=None): Comprueba que la expresión sea cierta.
  • assert_(expr, msg=None): Comprueba que la expresión sea cierta.
  • fail(msg=None): Falla inmediatamente.
  • failIf(expr, msg=None): Falla si la expresión es cierta.
  • failIfAlmostEqual(first, second, places=7, msg=None): Falla si los objetos pasados como parámetros son iguales hasta el séptimo decimal (o hasta el número de decimales indicado por places).
  • failIfEqual(first, second, msg=None): Falla si los objetos pasados como parámetros son iguales.
  • failUnless(expr, msg=None): Falla a menos que la expresión sea cierta.
  • failUnlessAlmostEqual(first, second, places=7, msg=None): Falla a menos que los objetos pasados como parámetros sean iguales hasta el séptimo decimal (o hasta el número de decimales indicado por places).
  • failUnlessEqual(first, second, msg=None): Falla a menos que los objetos pasados como parámetros sean iguales.
  • failUnlessRaises(excClass, callableObj, *args, **kwargs): Falla a menos que al llamar al objeto callableObj con los parámetros definidos por *args y**kwargs se lance una excepción de tipo excClass.
Como vemos todos los métodos cuentan con un parámetro opcional msg con un mensaje a mostrar cuando dicha comprobación falle.
Retomemos nuestra pequeña función para calcular el cuadrado de un número. Para probar el funcionamiento de la función podríamos hacer, por ejemplo, algo así:
  1. import unittest  
  2.   
  3. def cuadrado(num):  
  4.     """Calcula el cuadrado de un numero."""  
  5.   
  6.     return num ** 2  
  7.   
  8. class EjemploPruebas(unittest.TestCase):  
  9.     def test(self):  
  10.         l = [0123]  
  11.         r = [cuadrado(n) for n in l]  
  12.         self.assertEqual(r, [0149])  
  13.   
  14. if __name__ == "__main__":  
  15.     unittest.main()  

No hay comentarios:

Publicar un comentario