Skip to content. | Skip to navigation

Jan 18, 2009 - pylons, Python, contentmirror

Test Driven Development con Pylons

Una de las ideas principales destrás de Test Driven Development es escribir casos de tests antes que una funcioncionalidad.

Como comentaba en entradas anteriores, inicie un proyecto en Pylons. Iniciado como prueba de concepto, fue madurando y durante los ultimos dias estuve continuandolo. Antes de agregar cualquier funcionalidad, quise traerlo al 'proceso', lease extreme programming y bazaar, cosa que incluye Test Driven Development (TDD).

Una es una de las técnicas involucradas en TDD es Unit Testing. La diferencia entre Unit Testing y Functional Testing es sutil y suele ser motivo de confusión. Afortunadamente, Jeff Younker en su libro Foundation of Agile Python Development trata muy bien el tema y los define de la siguiente manera:

Unit Testing
Verifican el comportamiento de pequeñas secciones de código de un programa de forma aislada respecto al programa ensamblado.
Functional Testing
Verifica que la aplicación completa se comporta de la forma esperada.

En el libro trata otros tipos de testing que conpletan la lista:

  • Unit Testing: programmer tests, customer tests.
  • Functional Testing: exploratory testing, acceptance testing, integration testing, performance testing.
  • Regression Testing
  • Load Testing
  • Stress Testing

Despues de leer un par de páginas del libro y discutir algunas sutilezas de los conceptos con compañeros, baje el código de Plyne y luego agregue unit test. Como framework MVC que es Pylons, lo primero fueron los casos de tests para el modelo, tarea que no presento mayores dificultades. Cuando quise seguir con los controllers la cosa se complico. Primero porque la documentación de testing de Pylons no define unit tests en los controllers, sino que son functional test. Segundo porque al  ejecutar mis tests obtenia la excepción:

TypeError: No object (name: C) has been registered for this thread

esto ocurre cuando se quiere ejecutar código aislado del entorno WSGI y las variables del entorno no están configuradas. Despues de jugar un rato con mock objects, desisti. Escribi un mail a la lista de correos de Pylons y me fui a dormir. Sueño mediante, wiggy respondio con una respuesta bastante completa que cito a continuación.

from unittest import TestCase
from paste.registry import Registry
import pylons
from pylons.util import ContextObj
from pylons.controllers.util import Request

class MockTranslator:
    def ugettext(self, value):
        return value

class PylonsTestCase(TestCase):
    """A basic test case which allows access to pylons.c and pylons.request.
    """
    def setUp(self):
        self.registry=Registry()
        self.registry.prepare()

        self.context_obj=ContextObj()
        self.registry.register(pylons.c, self.context_obj)

        self.request_obj=Request(dict(HTTP_HOST="nohost"))
        self.registry.register(pylons.request, self.request_obj)

        self.translator_obj=MockTranslator()
        self.registry.register(pylons.translator, self.translator_obj)

Si se necesita acceso a una base de datos se puede usar:

class DatabaseTestCase(TestCase):
    def setUp(self):
        init_model(meta.engine)
        meta.metadata.create_all(meta.engine)

    def tearDown(self):
        meta.Session.remove()
        meta.metadata.drop_all(meta.engine

Y en caso que se necesiten ambos se puede heredar de ambas clases y llamar setUp ambos.

Ademas de resolver el problema, en la lista resurgio la discusión de Unit Testing vs Functional Testing y si el tema es de interese se puede seguir leyendo aca.

Filed under: , , , ,

Comments (0)

comments powered by Disqus