Модульное тестирование и имитация отправителя электронной почты на Python с помощью Google AppEngine

Я новичок в Python и движке приложений.

У меня есть этот код, который отправляет электронное письмо на основе параметров запроса после некоторой логики аутентификации. в моих модульных тестах (я использую GAEUnit), как я могу подтвердить, что электронное письмо с определенным содержанием было отправлено? - т.е. как мне издеваться над электронной почтой с помощью фальшивой электронной почты, чтобы убедиться, что отправка была вызвана?

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

И юнит-тесты,

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 

Спасибо за ссылку на GAEUnit. Я искал что-то подобное.

sastanin 09.01.2009 11:36
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
1
10 386
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Очень короткое введение содержит PyPI: MiniMock 1.0. Это очень маленькая библиотека для создания макетов.

  1. Вставьте свой макет в модуль, над которым нужно издеваться
  2. Определите, что вернет ваш макет
  3. Вызов метода
  4. Ваш макет скажет, какой метод был вызван.

Удачи!

Вы также можете переопределить метод _GenerateLog в mail_stub внутри AppEngine.

Вот родительский класс TestCase, который я использую в качестве миксина при тестировании отправки электронных писем:

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)

После этого примерный тестовый пример может выглядеть так:

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)

Посмотрите gae-testbed.googlecode.com, который предоставляет базовые классы, которые делают именно это.

JJ Geewax 13.09.2009 22:02

Этот проект выглядит многообещающим. Я надеюсь, что вы уже можете предоставить учебники, особенно те, которые предназначены для тестирования Mail API.

Randell 29.03.2010 19:58

Я использовал тестовый стенд GAE от jgeewax с GAEUnit. Мне было проще использовать GAEUnit вместо NoseGAE, поскольку у меня уже был GAEUnit. Вот шаги:

Добавьте GAEUnit в свое приложение

  1. Загрузите zip-архив GAEUnit с сайта его страница хостинга проекта Google Code.
  2. Распакуйте архив.
  3. Из папки, извлеченной из архива, скопируйте gaeunit.py в корневую папку вашего приложения.
  4. Добавьте следующие 2 строки к вашему app.yaml непосредственно под строкой с надписью handlers::

Код:

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

(Необязательно) В папке, извлеченной из архива, есть папка с именем sample_app, внутри которой находится измененная версия модуля webtest. Скопируйте модуль webtest (всю папку, содержащую debugapp.py и __init__.py) в корень вашего приложения.

Добавьте стенд GAE в GAEUnit:

  1. Загрузите tar-архив с gzip-архивом GAE Testbed с сайта его страница хостинга проекта Google Code.
  2. Распакуйте архив.
  3. Внутри распакованного архива находится модуль gaetestbed (это папка с именем «gaetestbed»). Скопируйте модуль в корень вашего приложения.
  4. Создайте файл в тестовой папке корня вашего приложения. Для этого примера назовем его test_mailer.py.
  5. Используя пример со страницы хостинга проекта Google Code на тестовой стенде GAE, добавьте в test_mailer.py следующие строки:

Код:

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)

Запустите свой сервер и перейдите к http://localhost:8080/test. Вы должны заметить, что (дополнительный) тест 1/1 был запущен с http://localhost:8080/test.

Источник: Использование тестовой системы GAE с GAEUnit: проверка того, что письмо было отправлено

Просто используйте следующее, чтобы получать все сообщения, отправленные после активации почтовой корешки.

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

У Google есть действительно простой способ сделать это в документация.

Вы создаете тестовую станцию ​​и почтовую заглушку в своей настройке следующим образом:

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

Запустите свой метод, а затем проверьте его так:

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

Другие вопросы по теме