Test de gestionnaires pour Python 2

L'exécution de tests unitaires pour votre application est décrite dans l'article relatif aux tests unitaires locaux pour Python. Si les tests unitaires constituent le meilleur moyen de tester les unités distinctes de votre code, l'intégration de ces unités de code est ce qui permet l'exécution de votre application. C'est pourquoi les tests d'intégration sont tout aussi importants.

Au niveau des applications App Engine, les gestionnaires de requêtes constituent des points d'intégration critiques. Alors qu'une application WSGI achemine les requêtes vers le bon gestionnaire, ce dernier traite lui-même les données de la requête et génère une réponse (reportez-vous à la section Gestionnaires de requêtes pour en savoir plus). Comme toute autre fonction ou classe, les gestionnaires de requêtes sont des objets Python usuels et sont donc faciles à utiliser dans les tests automatisés. Mais s'agissant d'une application WSGI qui encapsule ces objets de la même façon qu'une interface système, nous utiliserons une interface système similaire dans nos tests.

WebTest

Nous avons choisi le framework WebTest pour ces opérations. WebTest est une bibliothèque dotée d'une interface simple permettant de tester les applications basées sur WSGI, en particulier les gestionnaires de requêtes. Pour ce faire, une application WSGI est encapsulée dans une application de test spéciale, qui peut ensuite être utilisée pour les opérations de test. Même si vous ne disposez pas d'un environnement App Engine complet, WebTest vous permet d'interagir facilement avec vos gestionnaires, comme émettre des requêtes ou modifier l'environnement de celles-ci. Vous bénéficiez également d'une interface de réponse aux tests conviviale. WebTest est un outil conçu pour vous faciliter la tâche et n'a aucun caractère obligatoire.

Avant de commencer, installez WebTest sur votre ordinateur ou à l'emplacement que vous avez choisi pour exécuter les tests de gestionnaire. Les instructions correspondantes sont disponibles sur http://webtest.pythonpaste.org/#installation

Tester un gestionnaire de base "Hello World"

Commençons par tester un simple gestionnaire "Hello World!" qui répond à une requête utilisateur sous la forme d'un message en texte brut. La réponse du gestionnaire est "Hello World!" et le type de contenu est "text/plain" :

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!')

Ensuite, créez le scénario de test et initialisez une application de test qui utilise votre gestionnaire :

...
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')

Comme vous pouvez le constater, WebTest permet de créer des requêtes GET avec un simple appel get() (le même procédé est employé dans d’autres méthodes de requête). La valeur renvoyée est un objet de réponse qui vous permet de tester le code d'état, le corps et le type de contenu de la requête, entre autres éléments. Consultez la page d'accueil de WebTest pour découvrir toutes les opérations que vous pouvez effectuer.

Créer un test de gestionnaire qui utilise un service App Engine

Voyons maintenant comment tester un gestionnaire qui utilise un service App Engine. Pour ce faire, nous devons maintenant gérer deux composants susceptibles d'influencer nos tests : le gestionnaire et le service utilisé. Comme décrit dans l'article relatif aux tests unitaires locaux pour Python, l'outil testbed constitue le meilleur moyen de gérer les services lors de tests.

L'exemple suivant utilise Memcache, mais le processus est le même pour d'autres services tels que Datastore ou Task Queue.

Le gestionnaire que nous testons met en cache une clé et une valeur données. Notez que nous analysons les deux valeurs en fonction des paramètres de la requête.

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)

Dans le test, de la même façon qu'auparavant, créez d'abord une application que vous encapsulez ensuite avec WebTest. Activez en parallèle une instance de Testbed et veillez à la désactiver une fois le test réalisé.

...
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))

Configurer un framework de test

Vous pouvez configurer un framework de test si vous le souhaitez. Les tests de gestionnaires qui utilisent WebTest peuvent être exécutés de la même façon que vos tests unitaires pour App Engine. La seule différence est que vous devez avoir installé WebTest au préalable.