Commit f84207bd by Gabriel Falcão

Merge pull request #313 from lorin/django-mail-queue

Add Django email testing support
parents 2aae759c 234636c1
......@@ -262,6 +262,32 @@ Notice the ``terrain.py`` file at the project root, there you can
populate the :ref:`lettuce-world` and organize your features and steps
with it :)
Checking email
==============
When you run your Django server under lettuce, emails sent by your server
do not get transmitted over the Internet. Instead, these emails are
added to a :class:`multiprocessing.Queue` object at
``lettuce.django.mail.queue``.
Example:
.. highlight:: python
::
from lettuce import step
from lettuce.django import mail
from nose.tools import assert_equals
@step(u'an email is sent to "([^"]*?)" with subject "([^"]*)"')
def email_sent(step, to, subject):
message = mail.queue.get(True, timeout=5)
assert_equals(message.subject, subject)
assert_equals(message.recipients(), [to])
Running without HTTP server
===========================
......@@ -412,4 +438,4 @@ You can also specify it at ``settings.py`` so that you won't need to type the sa
.. _windmill: http://www.getwindmill.com/
.. _webdriver: http://code.google.com/p/selenium/wiki/PythonBindings?redir=1
.. _GAE: http://code.google.com/appengine
.. _locmem: https://docs.djangoproject.com/en/dev/topics/email/#in-memory-backend
\ No newline at end of file
.. _locmem: https://docs.djangoproject.com/en/dev/topics/email/#in-memory-backend
"""
Email backend that sends mails to a multiprocessing queue
"""
from lettuce.django import mail
from django.core.mail.backends.base import BaseEmailBackend
class QueueEmailBackend(BaseEmailBackend):
def send_messages(self, messages):
for message in messages:
mail.queue.put(message)
return len(messages)
......@@ -46,9 +46,15 @@ try:
except ImportError:
pass
from lettuce.django import mail
from lettuce.registry import call_hook
def create_mail_queue():
mail.queue = multiprocessing.Queue()
return mail.queue
class LettuceServerException(WSGIServerException):
pass
......@@ -104,10 +110,16 @@ class ThreadedServer(multiprocessing.Process):
lock = multiprocessing.Lock()
daemon = True
def __init__(self, address, port, *args, **kw):
def __init__(self, address, port, mail_queue, *args, **kw):
multiprocessing.Process.__init__(self)
self.address = address
self.port = port
self.mail_queue = mail_queue
def configure_mail_queue(self):
mail.queue = self.mail_queue
settings.EMAIL_BACKEND = \
'lettuce.django.mail.backends.QueueEmailBackend'
@staticmethod
def get_real_address(address):
......@@ -162,6 +174,8 @@ class ThreadedServer(multiprocessing.Process):
open(pidfile, 'w').write(unicode(os.getpid()))
self.configure_mail_queue()
connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
......@@ -217,7 +231,8 @@ class Server(object):
def __init__(self, address='0.0.0.0', port=None):
self.port = int(port or getattr(settings, 'LETTUCE_SERVER_PORT', 8000))
self.address = unicode(address)
self._actual_server = ThreadedServer(self.address, self.port)
queue = create_mail_queue()
self._actual_server = ThreadedServer(self.address, self.port, queue)
def start(self):
"""Starts the webserver thread, and waits it to be available"""
......
test:
PYTHONPATH=`pwd` DJANGO_SETTINGS_MODULE=djangoapp django-admin.py harvest email.feature
"""
A minimal Django app, just one file.
See: http://olifante.blogs.com/covil/2010/04/minimal-django.html
"""
import os
from django.conf.urls.defaults import patterns
from django.core.mail import send_mail
from django.http import HttpResponse
filepath, extension = os.path.splitext(__file__)
ROOT_URLCONF = os.path.basename(filepath)
INSTALLED_APPS = (
"lettuce.django"
)
def mail(request):
send_mail('Subject here', 'Here is the message.', 'from@example.com',
['to@example.com'], fail_silently=False)
return HttpResponse('Mail has been sent')
urlpatterns = patterns('', (r'^mail/$', mail))
Feature: Check email sent by Django server
Scenario: Access a web page which triggers an email
Given I visit "/mail/"
Then I see "Mail has been sent"
and an email is sent to "to@example.com" with subject "Subject here"
from lettuce import world, step
from lettuce.django import mail
from lettuce.django import django_url
from nose.tools import assert_equals
@step(u'I visit "([^"]*)"')
def visit(step, url):
world.browser.visit(django_url(url))
@step(u'I see "([^"]*)"')
def see(step, text):
assert world.browser.is_text_present(text)
@step(u'an email is sent to "([^"]*?)" with subject "([^"]*)"')
def email_sent(step, to, subject):
message = mail.queue.get(True, timeout=5)
assert_equals(message.subject, subject)
assert_equals(message.recipients(), [to])
from splinter.browser import Browser
from lettuce import before, after, world
@before.harvest
def setup(server):
world.browser = Browser()
@after.harvest
def cleanup(server):
world.browser.quit()
import os
import sys
import commands
from tests.asserts import assert_not_equals
from lettuce.fs import FileSystem
current_directory = FileSystem.dirname(__file__)
OLD_PYTHONPATH = os.getenv('PYTHONPATH', ':'.join(sys.path))
def teardown():
os.environ['PYTHONPATH'] = OLD_PYTHONPATH
def test_email():
'lettuce should be able to receive emails sent from django server'
os.environ['PYTHONPATH'] = current_directory
os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoapp'
status, out = commands.getstatusoutput(
"django-admin.py harvest email.feature --verbosity=2")
assert_not_equals(status, 0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment