Assuming an email implementation as simple as the accepted answer on this post, what can be the best way to write a unit test for the implementation? (I do not want to shoot emails to a valid recipient as part of testing the implementation)
-
Do you want to test `smtplib` module, or code you have written? – Tadeck Aug 16 '12 at 18:59
-
The code that I have written (inspired by the example mentioned in the post I mentioned :-) ) – name_masked Aug 16 '12 at 19:07
-
2If you don't want to test the smtplib itself, you could create a Mock to test your code without actually sending emails: http://pypi.python.org/pypi/MiniMock – Valdir Stumm Junior Aug 16 '12 at 19:14
-
What does your functions look like or objects? Usually you don't want to test some functionality that is already tested like the smtp module. You want to test your logic. – El Developer Aug 16 '12 at 19:17
-
Please mention the reason behind voting to close the thread. – name_masked Aug 17 '12 at 03:04
2 Answers
First, make the part responsible for sending / receiving pluggable. Just make sure you can switch the class / function / object responsible for connecting / sending / receiving messages to / from the server.
Second, make this part act as real thing. Make sure this class / function / object will fake original class's / function's / object's behaviour as close as possible (take the same parameters, throw the same errors).
Third, fake different behaviours of this part during tests. Different behaviours of this class in different tests may include:
- correct sending,
- delayed sending,
- connection timed out,
- successful receiving,
and, depending on what your module really does (and how flexible it is, eg. if it can be used by someone else for coding), you can also include these behaviours:
- error when incorrect parameters were passed,
- wide range of other exceptions found here: http://docs.python.org/library/smtplib.html
It really largely depends on what your module does. You need to test, if it does these things properly. Do not test smtplib
module, as it is already covered with tests. Do not test things irrelevant to your module - just things it does. It is possible, that some parts of your modules are untestable - in that case you have two options: change them to be testable, or leave them as they are (it is sometimes the most reasonable option for various reasons).

- 132,510
- 28
- 152
- 198
-
Oh, and test your code partially also (functions one-by-one), so you can quickly find out what started to behave incorrectly. – Tadeck Aug 16 '12 at 19:25
First of all, you can roughly call a unit test something you've described. Unit test usually refers to testing as small pieces of code as possible (without any network activity and I/O support).
So you can write a unittest to test message sending unit using mocks and stubs without actual message sending over network. Use mock to emulate different ways of message sending results:
- message sent correct
- timeout received when sending message
- message sent with a delay
The case you're talking about is usually referred to as integration testing, when you test interaction between different parts of your application, in your case: mail server and message sender.
So to test that you can do the next:
- Fire your function of message sending.
- Use poplib or imaplib modules to check if mail came to your mailbox.
Here's an example of how poplib works:
import getpass, poplib
M = poplib.POP3('localhost')
M.user(getpass.getuser()) # Assuming that mailbox has your OS user/pass
M.pass_(getpass.getpass())
numMessages = len(M.list()[1])
for i in range(numMessages):
for j in M.retr(i+1)[1]:
print j
This is an example of how to retrieve message using poplib (shamelessly taken from official documentation of poplib). Similarly you can use imaplib. It depends on what technologies does your mail server support.
Note! You must remember that writing test is not always that simple. Your code must be adapted for unittesting, e.g. when you want to test mail sending, your sender function/class must be called/initialized with message sending object (SMTP in our case), that can be emulated (replaced with mock object) during testing.

- 39,424
- 5
- 49
- 62