Test degli handler per Python 2

L'articolo Test delle unità locali per Python descriveva come eseguire i test delle unità per la tua applicazione. Sebbene i test delle unità siano ottimi per testare le singole unità di codice, l'integrazione di queste unità di codice è ciò che fa funzionare l'applicazione, quindi i test di integrazione sono altrettanto importanti.

Per le applicazioni App Engine, i gestori delle richieste sono punti di integrazione critici. Mentre un'applicazione WSGI indirizza le richieste al gestore corretto, il gestore stesso elabora i dati della richiesta e genera una risposta (scopri di più sui gestori delle richieste). I gestori delle richieste sono normali oggetti Python come qualsiasi altra funzione o classe, il che li rende facili da utilizzare nei test automatizzati. Ma poiché un'applicazione WSGI li racchiude come una shell, utilizzeremo una shell simile nei nostri test.

WebTest

Per i nostri test, utilizzeremo il framework WebTest. WebTest è una libreria che offre un'interfaccia semplice per testare le applicazioni basate su WSGI e quindi i gestori delle richieste. A questo scopo, esegue il wrapping di un'applicazione WSGI in un'app di test speciale che può essere utilizzata per i test. WebTest ti consente di interagire con i gestori senza un ambiente App Engine completo. Puoi inviare facilmente richieste e modificare l'ambiente di richiesta. Le risposte hanno anche un'interfaccia adatta ai test. Non devi usare WebTest, ma ti semplifica molto la vita.

Prima di iniziare, installa WebTest sulla tua macchina locale o ovunque intendi eseguire i test dei gestori. Le istruzioni sono disponibili all'indirizzo http://webtest.pythonpaste.org/#installation

Test di un semplice gestore "Hello World"

Iniziamo testando un semplice gestore "Hello World!" che risponde a una richiesta utente con una risposta in testo normale. La risposta dell'handle è "Hello World!" e il tipo di contenuto è "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!')

Successivamente, crea lo scenario di test e inizializza un'applicazione di test che utilizza il tuo gestore:

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

Come puoi vedere, WebTest ti consente di effettuare richieste GET con una semplice chiamata get() (altri metodi di richiesta hanno metodi simili). Il valore restituito è un oggetto risposta con cui puoi testare il codice di stato, il corpo, il tipo di contenuti e molto altro ancora. Consulta la home page di WebTest per una descrizione dettagliata di tutte le operazioni che puoi eseguire.

Creazione di un test del gestore che utilizza un servizio App Engine

Ora vediamo come testare un gestore che utilizza un servizio App Engine. Ciò significa che ora dobbiamo occuparci di due componenti che potrebbero influire sui nostri test: l'handler e il servizio che stiamo utilizzando. Come descritto nell'articolo Test locali delle unità per Python, il modo migliore per gestire i servizi nei test è utilizzare testbed.

L'esempio seguente utilizza Memcache, ma il principio è lo stesso per altri servizi come Datastore o Task Queue.

Il gestore che testiamo memorizza nella cache la chiave e il valore specificati. Tieni presente che analizziamo entrambi i valori dai parametri di richiesta.

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)

Nel test, come prima, crea prima un'applicazione e racchiudila in WebTest. Inoltre, attiva un'istanza Testbed e disattivala dopo il test.

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

Configurazione di un framework di test

Se vuoi, puoi configurare un framework di test. I test per i gestori che utilizzano WebTest possono essere eseguiti come i test delle unità per App Engine. L'unica differenza è che devi assicurarti di aver installato WebTest.