2009-01-09 8 views
5

Je suis un novice de python et du moteur d'applications.Test d'unité et simulation d'expéditeur d'e-mails en Python avec Google AppEngine

J'ai ce code qui envoie un email basé sur des paramètres de requête après une certaine logique d'authentification. dans mes tests unitaires (j'utilise GAEUnit), comment puis-je confirmer qu'un e-mail avec des contenus spécifiques a été envoyé? - c'est-à-dire comment je me moque de l'emailer avec un faux emailer pour vérifier que l'envoi a été appelé?

class EmailHandler(webapp.RequestHandler): 
def bad_input(self): 
    self.response.set_status(400) 
    self.response.headers['Content-Type'] = 'text/plain' 
    self.response.out.write("<html><body>bad input </body></html>") 

def get(self): 
    to_addr = self.request.get("to") 
    subj = self.request.get("subject") 
    msg = self.request.get("body") 
    if not mail.is_email_valid(to_addr): 
    # Return an error message... 
    # self.bad_input() 
    pass 

    # authenticate here 

    message = mail.EmailMessage() 
    message.sender = "[email protected]" 
    message.to = to_addr 
    message.subject = subj 
    message.body = msg 
    message.send() 
    self.response.headers['Content-Type'] = 'text/plain' 
    self.response.out.write("<html><body>success!</body></html>") 

Et les tests unitaires,

import unittest 
from webtest import TestApp 
from google.appengine.ext import webapp 
from email import EmailHandler 

class SendingEmails(unittest.TestCase): 

    def setUp(self): 
    self.application = webapp.WSGIApplication([('/', EmailHandler)], debug=True) 

    def test_success(self): 
    app = TestApp(self.application) 
    response = app.get('http://localhost:8080/[email protected]&body=blah_blah_blah&subject=mySubject') 
    self.assertEqual('200 OK', response.status) 
    self.assertTrue('success' in response) 
    # somehow, assert email was sent 
+0

Merci pour le lien vers GAEUnit. Je cherchais quelque chose comme ça. – sastanin

Répondre

2

Une très courte introduction fournit PyPI: MiniMock 1.0. C'est une très petite bibliothèque pour établir des simulacres.

  1. Injecter votre maquette dans le module, qui devrait être moquée
  2. Define, ce que votre maquette retournera
  3. Appelez la méthode
  4. Votre maquette dira que la méthode a été appelée.

Bonne chance!

3

Vous pouvez également remplacer la méthode _GenerateLog dans mail_stub dans AppEngine.

Voici une classe TestCase mère que je l'utilise comme mixin lors du test que les e-mails sont envoyés:

from google.appengine.api import apiproxy_stub_map, mail_stub 

__all__ = ['MailTestCase'] 

class MailTestCase(object): 
    def setUp(self): 
     super(MailTestCase, self).setUp() 
     self.set_mail_stub() 
     self.clear_sent_messages() 

    def set_mail_stub(self): 
     test_case = self 
     class MailStub(mail_stub.MailServiceStub): 
      def _GenerateLog(self, method, message, log, *args, **kwargs): 
       test_case._sent_messages.append(message) 
       return super(MailStub, self)._GenerateLog(method, message, log, *args, **kwargs) 

     if 'mail' in apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map: 
      del apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map['mail'] 

     apiproxy_stub_map.apiproxy.RegisterStub('mail', MailStub()) 

    def clear_sent_messages(self): 
     self._sent_messages = [] 

    def get_sent_messages(self): 
     return self._sent_messages 

    def assertEmailSent(self, to=None, sender=None, subject=None, body=None): 
     for message in self.get_sent_messages(): 
      if to and to not in message.to_list(): continue 
      if sender and sender != message.sender(): continue 
      if subject and subject != message.subject(): continue 
      if body and body not in message.textbody(): continue 
      return 

     failure_message = "Expected e-mail message sent." 

     args = [] 
     if to: args.append('To: %s' % to) 
     if sender: args.append('From: %s' % sender) 
     if subject: args.append('Subject: %s' % subject) 
     if body: args.append('Body (contains): %s' % body) 

     if args: 
      failure_message += ' Arguments expected: ' + ', '.join(args) 

     self.fail(failure_message) 

Après cela, un test de l'échantillon pourrait ressembler à:

import unittest, MailTestCase 

class MyTestCase(unittest.TestCase, MailTestCase): 
    def test_email_sent(self): 
     send_email_to('[email protected]') # Some method that would send an e-mail. 
     self.assertEmailSent(to='[email protected]') 
     self.assertEqual(len(self.get_sent_messages()), 1) 
+1

Découvrez http://gae-testbed.googlecode.com qui donne les classes de base qui font exactement cela. –

+0

Ce projet semble prometteur. J'espère que vous pouvez déjà fournir les tutoriels, en particulier celui pour tester l'API Mail. – Randell

1

J'ai utilisé GAE Testbed de jgeewax avec GAEUnit. Utiliser GAEUnit au lieu de NoseGAE était plus facile pour moi puisque j'avais déjà mis en place GAEUnit. Voici les étapes:

Ajouter GAEUnit à votre application

  1. Téléchargez l'archive compressée de GAEUnit de its Google Code project hosting page.
  2. Extrayez l'archive.
  3. Dans le dossier extrait de l'archive, copiez gaeunit.py dans le dossier racine de votre application.
  4. Ajouter les 2 lignes à votre app.yaml, directement sous la ligne suivante qui dit handlers::

code:

- url: /test.* 
    script: gaeunit.py 

(Facultatif) Dans le dossier extrait de l'archive, il y a un dossier nommé sample_app et à l'intérieur il est la version modifiée du module webtest. Copiez le module webtest (le dossier entier contenant debugapp.py et __init__.py) à la racine de votre application.

Ajouter GAE Testbed à GAEUnit:

  1. Télécharger le goudron GAE Testbed gzip archive à partir its Google Code project hosting page.
  2. Extrayez l'archive.
  3. L'intérieur de l'archive extraite est le module gaetestbed (c'est le dossier nommé "gaetestbed"). Copiez le module à la racine de votre application.
  4. Créez un fichier dans le dossier de test de la racine de votre application. Par souci de cet exemple, nommons-le test_mailer.py.
  5. En utilisant l'exemple de la page d'accueil du projet GAE Testbed Google Code, ajoutez les lignes suivantes à test_mailer.py:

code:

import unittest 
from gaetestbed import MailTestCase 

class MyTestCase(MailTestCase, unittest.TestCase): 
    def test_email_sent(self): 
     send_email_to('[email protected]') # Some method that sends e-mail... 
     self.assertEmailSent(to='[email protected]') 
     self.assertEqual(len(self.get_sent_messages()), 1) 

Démarrez votre serveur et allez à http://localhost:8080/test. Vous devriez remarquer que (un test supplémentaire) de 1/1 a été exécuté à partir de http://localhost:8080/test.

Source: Using GAE Testbed with GAEUnit: Testing that email was sent

2

Il suffit d'utiliser les éléments suivants pour obtenir tous les messages envoyés depuis l'activation du stub mail.

from google.appengine.api import apiproxy_stub_map 
sent_messages = apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map['mail'].get_sent_messages() 
2

Google a un moyen très simple de le faire dans leur documentation.

Vous créez un banc d'essai et le talon de courrier dans votre configuration comme ceci:

self.testbed = testbed.Testbed() 
self.testbed.activate() 
self.testbed.init_mail_stub() 
self.mail_stub = self.testbed.get_stub(testbed.MAIL_SERVICE_NAME) 

Exécutez votre méthode, puis vérifier comme ceci:

messages = self.mail_stub.get_sent_messages(to='[email protected]') 
self.assertEqual(1, len(messages)) 
self.assertEqual('[email protected]', messages[0].to) 
Questions connexes