I routinely give the class "Python For Testers" where I teach testers how to craft their own small tools to assist them in their testing.

The thing is, even though I have a background as both a tester and developer, and I've based large parts of my career on test automation, I still think we must have the thinking tester in the driving seat when it comes to testing and then use the automation for the checking.

Checking/Testing

Wondering about the distinction between testing and checking? Then I encourage you to look at this blog post by Michael Bolton (@michaelbolton) and James Bach (@jamesmarcusbach):

Testing and Checking refined

Manual and repetitive work == Yawn...

A lot of times as testers we have boring, repetitive, and even time consuming tasks that simply needs to get done before, during, or after we perform our testing.
But as I say in Python For Testers: "Who says it has to be done by you?"

There are times when you automate some job, preferably by using Python of course..., and you don't want to stick around waiting for the result.
Coffee may be calling, colleagues want to go out to lunch, or you may just want to get on with another task and wait until your current job is finished.

In those scenarios it's very nice if you can get some notification from your Python program saying the job is done, and even say if it succeeded or failed, and perhaps include some log files in case of a failure to analyze.

Mailgun

Well, then Mailgun comes ot the rescue with their official title:

"The Email Service For Developers"

Well you know what... I'm going to encourage them to change that into:

"The Email Service For Developers and Testers"

Mailgun is a free email service (10.000 free emails/month) geared specifically towards people who want to integrate sending emails into their applications and scripts.
It's just an API call away...

So head over to Mailgun and register for your free account, if you have your own domain (mine is of course "northerntest.se") you can of course make sure Mailgun sends from that as well.
In the examples below we use the public API key for demo purposes provided by Mailgun, but its easy to find your own API key under the main dashboard.

Go Hedwig go!

If you wan't to send an email straight from the command line (assuming you have a unix-like system with curl installed), then you just issue the following command:

curl -s --user 'api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0' \
    https://api.mailgun.net/v3/samples.mailgun.org/messages \
	-F from='Excited User <excited@samples.mailgun.org>' \
    -F to='devs@mailgun.net' \
	-F subject='Hello' \
    -F text='Testing some Mailgun awesomeness!

If you want to do this from a Python script then you can of course settle with a quick and dirty (and a bit ugly) way and just wrap the command above into a string and send it into: os.system()

But there's a nicer way that I would recommend, and that is using the awesome library "Requests".

At that point the only code you need is the following:

import requests
requests.post("https://api.mailgun.net/v3/samples.mailgun.org/messages",
                auth=("api", 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0'),
                data={"from": 'Harry Potter <harry.potter@hogwarts.co.uk>',
                      "to": 'Hermione Granger <hermione.granger@hogwarts.co.uk>',
                      "subject": 'Forgot my notes...',
                      "text": 'Can I copy your notes from todays potions class???'})

And its of course easy to break out the from, to, subject, text values into variables instead.

Helper module

a while back I gave a full-day tutorial at Nordic Testing Days in Estonia "Taming the Terminal-based Applications and Testing Them"

In this tutorial I wanted the participants to try and send emails after their scripts finished executing, so I showed them how you can create your own python module to create certain convenient methods in there:

File mailgun.py:

import requests

class Mailgun:

api = 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0'

def sendEmail(self, sender='NTD 2015 <kristoffer.nordstrom@northerntest.se>', to='kristoffer.nordstrom@northerntest.se', subject='Greetings from Tallinn', message='Do you like Python? Why not consider partaking in Python For Testers! http://www.northerntest.se/training.html'):

    print "Sending email to: " + to
    requests.post("https://api.mailgun.net/v3/samples.mailgun.org/messages",
                auth=("api", self.api),
                data={"from": sender,
                      "to": to,
                      "subject": subject,
                      "text": message})`

At which point they only had to import the library and call the method.

from mailgun import Mailgun

'''
some long running task
'''
mg = Mailgun()
mg.sendEmail('myemail@mycompany.com',
			 'myteam@mycompany.com',
             'Check completed',
             'You can look into the results now.')

Attaching files to the email

But you may ask yourself how to attach files to the email?
No sweat, I included that as a separate method in the help-module provided.

File mailgun.py:

import requests

class Mailgun:

def sendEmailWithAttachement(self, sender, to, subject, message, attachement):
    requests.post("https://api.mailgun.net/v3/samples.mailgun.org/messages",
                auth=("api", self.api),
                files=[("attachment", open(attachement))],
                data={"from": sender,
                      "to": to,
                      "subject": subject,
                      "text": message})

As you can see you only add the "files" parameter to the call and send in a file object.
The method I wrote "sendEmailWithAttachement" just takes the path to the file to attach and opens it (Note: in production you should of course try to make some validation to make sure the file exists etc).

And now you can update your script to include log files whenever necessary, for example upon failure.

from mailgun import Mailgun

'''
some long running task
'''
mg = Mailgun()

mg.sendEmail('Hermione Granger <hermione.granger@hogwarts.co.uk>',
	'Harry Potter <harry.potter@hogwarts.co.uk>',
    'Notes from potions class 1996-11-19',
    'Seriously Harry... don't you have that "special" potions book to help you...',
    '/home/hg91/notes/PotionsClass/96/November/Notes_1996_11_19.txt')

So now you've seen how easy it is to include email capabilities into your test scripts to send not only notifications upon completion, but also to add attachements.

Want to attend Python For Testers?

Want to attend Python For Testers and live in Sweden/Denmark? Then you should know I'm coming to Stockholm on 15-16/9 (Information and registeration) and Copenhagen 5-6/10 (Information and registeration).