[Tutor] Writing unit tests that involve email

Arnel Legaspi jalespring at gmail.com
Tue Jul 16 01:16:18 CEST 2013


On Sun, Jul 14, 2013 at 8:32 AM, Arnel Legaspi <jalespring at gmail.com> wrote:

> Hello,
>
> I have written a small Python script that allows the user to post to
> their blogs via email, converting the draft written in Markdown &
> sending it to a blog's email address (like what they had in Posterous
> back then).
>
> https://bitbucket.org/acl79/**downpost<https://bitbucket.org/acl79/downpost>
>
> At this point, I've been trying to write unit tests for it to get some
> practice writing unit tests for other possibly larger projects in the
> future. I've been using the dsmtpd script available at:
>
> https://github.com/matrixise/**dsmtpd<https://github.com/matrixise/dsmtpd>
>
> to run a SMTP server in the background and route all the emails being
> sent by my script to localhost. The script allows saving the messages to
> an optional Maildir directory, and I wanted to use that to be able to
> check various fields in the email for correctness in the unit tests.
>
> What I'm having difficulty is getting the unit tests to properly run the
> script being tested and send the email, get the proper Maildir message,
> and be able to read it via the unit test script. Right now, even when
> the SMTP server is not running, all the tests for checking the sent
> email pass, which is not what I intended.
>
> I know the SMTP server works, because if I send some email using another
> Python or Powershell script, the script logs on the screen that it did
> receive the email.
>
> How should I approach this?
>
> Here is the unit test script I have (some lines may get wrapped):
>
> #!/usr/bin/env python
>
> import os
> import sys
> import argparse
> import ConfigParser
> import unittest
> import mailbox
>
> MKDOWN_TEXT = """
> **Lorem ipsum dolor sit amet**, consectetur adipiscing elit. Sed
> dapibus dui nibh, ut fermentum dolor tristique fringilla. Pellentesque
> tristique sagittis dapibus. Nunc pellentesque nisi vitae arcu lacinia,
> nec ultricies libero rutrum. *Vivamus* enim augue, malesuada in dui ac,
> laoreet faucibus dolor.
>
> * Aliquam eu nisi dictum, tristique eros ut, eleifend elit.
> * Pellentesque lacinia sodales erat non rhoncus.
> * Aliquam mattis ullamcorper purus sit amet sodales.
>
> Ut mollis ligula id sapien vehicula fringilla eu auctor diam.
> Praesent consequat tristique arcu, nec iaculis metus porta at.
> Nam mauris orci, congue vel consectetur vitae, viverra adipiscing
> urna.
>
>  > Donec tristique leo erat, sit amet feugiat velit semper sit amet.
>  > Nunc sagittis libero risus, at mollis mauris pharetra quis. Vivamus
>  > adipiscing porttitor velit, sit amet sodales risus mollis quis.
>
> Donec sed risus orci. Cras fringilla at lorem ut venenatis.
> Pellentesque varius lorem neque, euplace rat eros dictum nec.
> """
>
> HTML_TXT = """
> <p><strong>Lorem ipsum dolor sit amet</strong>, consectetur adipiscing
> elit. Sed
> dapibus dui nibh, ut fermentum dolor tristique fringilla. Pellentesque
> tristique sagittis dapibus. Nunc pellentesque nisi vitae arcu lacinia,
> nec ultricies libero rutrum. <em>Vivamus</em> enim augue, malesuada in
> dui ac,
> laoreet faucibus dolor.</p>
> <ul>
> <li>Aliquam eu nisi dictum, tristique eros ut, eleifend elit.</li>
> <li>Pellentesque lacinia sodales erat non rhoncus.</li>
> <li>Aliquam mattis ullamcorper purus sit amet sodales.</li>
> </ul>
> <p>Ut mollis ligula id sapien vehicula fringilla eu auctor diam.
> Praesent consequat tristique arcu, nec iaculis metus porta at.
> Nam mauris orci, congue vel consectetur vitae, viverra adipiscing
> urna.</p>
> <blockquote>
> <p>Donec tristique leo erat, sit amet feugiat velit semper sit amet.
> Nunc sagittis libero risus, at mollis mauris pharetra quis. Vivamus
> adipiscing porttitor velit, sit amet sodales risus mollis quis.</p>
> </blockquote>
> <p>Donec sed risus orci. Cras fringilla at lorem ut venenatis.
> Pellentesque varius lorem neque, euplace rat eros dictum nec.</p>
> """
>
> TESTARGS = []
>
>
> def clear_args():
>      """
>      Clear the arguments & the internal list (TESTARGS) used
>      for test arguments. This is needed to allow the script to
>      be tested with different arguments.
>      """
>      del sys.argv[1:]
>      TESTARGS[:] = []
>      return
>
>
> def add_testfiles(contentfile='pos**t.md <http://post.md>',
> configfile='blog.conf'):
>      """
>      Clear the arguments & the internal list used. Add the
>      regular test files into the argument list instead.
>      """
>      clear_args()
>      TESTARGS.append(contentfile)
>      TESTARGS.append(configfile)
>      TESTARGS.append('--debug')
>      sys.argv.append(TESTARGS)
>      return
>
>
> def create_configfile():
>      """
>      Create a dummy config file for testing purposes.
>      """
>      parser = ConfigParser.SafeConfigParser(**allow_no_value=True)
>      parser.add_section('blog')
>      parser.set('blog', 'email', 'test at email.net')
>      parser.add_section('smtp')
>      parser.set('smtp', 'server', '127.0.0.1')
>      parser.set('smtp', 'port', '8000')
>      parser.set('smtp', 'username', 'user at wherever.com')
>      parser.set('smtp', 'password', 'DeJpkZa3WL')
>
>      with open('blog.conf', 'wb') as configfile:
>          parser.write(configfile)
>
>
> class TestReadingSendingPostFile(**unittest.TestCase):
>
>      def setUp(self):
>          """ Prepare a post file for testing. """
>          create_configfile()
>          with open('post.md', 'wb') as postfile:
>              postfile.write(MKDOWN_TEXT)
>          self.mbox = mailbox.Maildir('mail_dir')
>
>      def test_wrongconfigfile(self):
>          clear_args()
>          add_testfiles('post.md', 'bloginfo.ini')
>          self.assertRaises(IOError)
>
>      def test_wrongpostfile(self):
>          clear_args()
>          add_testfiles('some_**nonexistent_file.md<http://some_nonexistent_file.md>',
> 'blog.conf')
>          self.assertRaises(IOError)
>
>      def test_sendpost(self):
>          clear_args()
>          add_testfiles()
>          for message in self.mbox:
>              self.assertEqual(message['**subject'], 'post')
>              self.assertEqual(message.get_**payload(), HTML_TXT)
>
>      def test_sendrawpost(self):
>          clear_args()
>          TESTARGS.append('--raw')
>          add_testfiles()
>          for message in self.mbox:
>              self.assertEqual(message['**subject'], 'post')
>              self.assertEqual(message.get_**payload(), MKDOWN_TEXT)
>
>      def test_sendpost_withunderscores(**self):
>          clear_args()
>          os.rename('post.md',
> 'This_Should_Be_Posted_**Without_Underscores.md')
>          add_testfiles('This_Should_Be_**Posted_Without_Underscores.md'**,
>                        'blog.conf')
>          for message in self.mbox:
>              self.assertEqual(message['**subject'],
>                               'This Should Be Posted Without Underscores')
>              self.assertEqual(message.get_**payload(), HTML_TXT)
>
>      def test_sendpost_withspaces(self)**:
>          clear_args()
>          os.rename('post.md', 'This Should Be Posted As Is.md')
>          add_testfiles('This Should Be Posted As Is.md', 'blog.conf')
>          for message in self.mbox:
>              self.assertEqual(message['**subject'],
>                               'This Should Be Posted As Is')
>              self.assertEqual(message.get_**payload(), HTML_TXT)
>
>      def test_sendpost_withsettitle(**self):
>          clear_args()
>          TESTARGS.append('-t "This will be the new title"')
>          add_testfiles()
>          for message in self.mbox:
>              self.assertEqual(message['**subject'],
>                               'This will be the new title')
>              self.assertEqual(message.get_**payload(), HTML_TXT)
>
>      def tearDown(self):
>          if os.path.exists('post.md'):
>              os.remove('post.md')
>          if os.path.exists('This_Should_**Be_Posted_Without_Underscores.**
> md'):
>              os.remove('This_Should_Be_**Posted_Without_Underscores.md'**)
>          if os.path.exists('This Should Be Posted As Is.md'):
>              os.remove('This Should Be Posted As Is.md')
>
>          os.remove('blog.conf')
>
>
> if __name__ == '__main__':
>      argp = argparse.ArgumentParser()
>      argp.add_argument('unittest_**args', nargs='*')
>      args = argp.parse_args()
>      unit_args = [sys.argv[0]] + args.unittest_args
>      unittest.main(argv=unit_args)
>
>
> Any comments on this & the script I'm writing tests for would be
> appreciated.
>

Hello,

Is there any other information needed here so I can get help re: my unit
tests?
Perhaps I did something wrong with my post?
I'm using Python 2.7.5 on Windows 7 x64, but the script I'm writing tests
for has branches for both Python 2 and 3.

I'm pretty sure I've made a number of mistakes here, as I have not written
any unit tests before this.

Thank you,
Arnel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20130716/3359f91c/attachment-0001.html>


More information about the Tutor mailing list