Prueba del controlador para Python 2

En el artículo Prueba de unidades locales para Python, se describe cómo ejecutar las pruebas de unidades de la aplicación. Si bien las pruebas de unidades son ideales para probar las unidades del código por separado, la integración de esas unidades de código es lo que hace que la aplicación se ejecute, por eso, la prueba de integración es igual de importante.

Para aplicaciones de App Engine, los controladores de solicitudes son puntos de integración fundamentales. Una aplicación de WSGI dirige las solicitudes al controlador correcto, y este procesa los datos de la solicitud y genera una respuesta (obtén más información sobre los Controladores de solicitudes). Los controladores de solicitudes son objetos normales de Python como cualquier otra función o clase, lo que permite que sean fáciles de usar en pruebas automatizadas. Sin embargo, dado que una aplicación de WSGI los agrupa como una shell, usaremos una shell similar en nuestras pruebas.

WebTest

Para nuestras pruebas, utilizaremos el marco de trabajo de WebTest. WebTest es una biblioteca que te ofrece una interfaz simple para probar las aplicaciones basadas en WSGI y, por lo tanto, los controladores de solicitudes. Para ello, une una aplicación de WSGI con una aplicación de prueba especial que luego se pueda usar con el fin de realizar pruebas. WebTest te permite interactuar con tus controladores sin un entorno de App Engine completo. Puedes enviar solicitudes y modificar el entorno de la solicitud con facilidad. Las respuestas también tienen una interfaz intuitiva para las pruebas. No tienes que usar WebTest, pero seguro simplifica tu vida.

Antes de comenzar, instala WebTest en tu máquina local o donde decidas ejecutar las pruebas del controlador. Las instrucciones se pueden encontrar en http://webtest.pythonpaste.org/#installation

Prueba un controlador simple de “Hello World”

Comencemos con la prueba de un controlador simple de “Hello World!” que responde a una solicitud de usuario con una respuesta de texto sin formato. La respuesta del controlador es “Hello World!” y el tipo de contenido es “texto/sin formato”:

import webapp2
import webtest

class HelloWorldHandler(webapp2.RequestHandler):
   def get(self):
       # Create the handler's response "Hello World!" in plain text.
       self.response.headers['Content-Type'] = 'text/plain'
       self.response.out.write('Hello World!')

Crea el caso de prueba y, luego, inicializa una aplicación de prueba que use tu controlador:

...
class AppTest(unittest.TestCase):
    def setUp(self):
        # Create a WSGI application.
        app = webapp2.WSGIApplication([('/', HelloWorldHandler)])
        # Wrap the app with WebTest’s TestApp.
        self.testapp = webtest.TestApp(app)

    # Test the handler.
    def testHelloWorldHandler(self):
        response = self.testapp.get('/')
        self.assertEqual(response.status_int, 200)
        self.assertEqual(response.normal_body, 'Hello World!')
        self.assertEqual(response.content_type, 'text/plain')

Como puedes ver, WebTest te permite realizar solicitudes GET con una llamada get() simple (otros métodos de solicitud tienen métodos similares). El valor de retorno es un objeto de respuesta con el que puedes probar el código de estado, cuerpo, el tipo de contenido y mucho más. Consulta la página principal de WebTest para obtener una descripción detallada de todas las funciones que puedes realizar.

Crea una prueba de controlador que use un servicio de App Engine

Ahora observemos cómo probar un controlador que usa un servicio de App Engine. Esto significa que debemos lidiar con dos componentes que pueden afectar nuestras pruebas: el controlador y el servicio que usamos. Según se describe en el artículo Pruebas de unidades locales para Python, la mejor forma de abordar los servicios en las pruebas es usar testbed.

En el siguiente ejemplo, se usa Memcache, aunque es el mismo principio que se aplica en otros servicios, como Datastore o Lista de tareas en cola.

El controlador que probamos almacena en caché la clave y el valor que se proporcionan. Ten en cuenta que analizamos ambos valores a partir de los parámetros de solicitud.

from google.appengine.api import memcache
from google.appengine.ext import testbed
import webapp2
import webtest

class CacheHandler(webapp2.RequestHandler):
  def post(self):
    key = self.request.get('key')
    value = self.request.get('value')
    memcache.set(key, value)

En la prueba, al igual que antes, primero debes crear una aplicación y, luego, unirla con WebTest. Además, debes activar una instancia de Testbed y tener cuidado de no desactivarla después de la prueba.

...
class AppTest(unittest.TestCase):

  def setUp(self):
    app = webapp2.WSGIApplication([('/cache/', CacheHandler)])
    self.testapp = webtest.TestApp(app)
    self.testbed = testbed.Testbed()
    self.testbed.activate()

  def tearDown(self):
     self.testbed.deactivate()

  def testCacheHandler(self):
    # First define a key and value to be cached.
    key = 'answer'
    value = '42'
    self.testbed.init_memcache_stub()
    params = {'key': key, 'value': value}
    # Then pass those values to the handler.
    response = self.testapp.post('/cache/', params)
    # Finally verify that the passed-in values are actually stored in Memcache.
    self.assertEqual(value, memcache.get(key))

Configura un framework de prueba

Puedes configurar un marco de trabajo de prueba si lo deseas. Las pruebas para controladores que usan WebTest se pueden ejecutar como tus pruebas de unidades de App Engine. La única diferencia es que debes asegurarte de tener instalado WebTest.