Archive

Posts Tagged ‘unit’

Stubbing a Test Mail Server

February 17, 2009 1 comment

Django has built in support for sending email. We make use of this in our app, but when testing, we wanted to be able to access the emails sent so we could assert on their content, and pull data out of the body. In the unit tests, that’s easily solved by mocking the email client call, but we wanted to do this as a black-box regression test. That’s where the Python built in smtpd.SMTPServer comes in handy:

import smtpd, asyncore, threading

email_server = None

class FakeServer(smtpd.SMTPServer):

def __init__(self, localaddr, remoteaddr):
self.server = smtpd.SMTPServer.__init__(self, localaddr, remoteaddr)
self.emails = {}

def process_message(self, peer, mailfrom, rcpttos, data):
for recipient in rcpttos:
idx = recipient.replace(‘@’,’_at_’).replace(‘.’,’_dot_’)
existing_emails = emails.get(idx, [])
existing_emails.append(data)
emails[idx] = existing_emails

def stop(self):
self.server.close()

def main()
email_server = FakeServer((‘localhost’, 10920), None)
def start_email():
asyncore.loop()
thread = threading.Thread(target=start_email)
thread.setDaemon(True)
thread.start()

if __name__==’__main__’:
main()

This starts an email server on port 10910, which on receipt of a new email, stores it in a dictionary keyed by a modified version of the email address. Multiple emails to the same address get appended to the list. There is no reason in this context for replacing the ‘.’ and ‘@’ symbols from the email address in this context, but it was appropriate for our usage.

We run the stub mailserver on a separate box, and make the emails available via a get request on a test HTTP server, which allows us to run tests scripted entirely written in Selenium. I will blog again with details of how we manage our test HTTP server. You can use the this code as the basis for embedding the mail server in a unittest setup too.

By: Chris Tarttelin

Creating Fixtures from Within Tests

February 3, 2009 Comments off

Django gives you a ‘dumpdata’ target which will create a fixture from all the records in your schema. For what we wanted, this was overkill. We had an existing unit test which was creating data in one test, and it was just the right amount of data for what we wanted. After searching through the Django codebase, it became clear that we could pass the objects we had in that test straight to the JSON serializer, and write the output to file. This ended up looking something like this:-

from django.core.serializers import json
serializer = json.Serializer()
objectsToSerialize =
MyModel.objects.filter(column='restriction')
with open('my_fixture.json','w') as f:
. f.write(serializer.serialize(objectsToSerialize, indent=4))

And that’s it! You can also spin up a shell, using:-

python manage.py shell

and load the data you want to create fixtures from if you don’t have any tests that create the data you want already.

By: Chris Tarttelin