From 6d94e947369459c40976c76651fb15e65085df01 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 13 May 2015 16:27:38 -0700 Subject: [PATCH] Live API tests Addresses #41. (Still need to add a Mandrill test key to the Travis config.) --- djrill/tests/__init__.py | 2 + djrill/tests/test_mandrill_integration.py | 88 +++++++++++++++++++++++ docs/contributing.rst | 10 ++- 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 djrill/tests/test_mandrill_integration.py diff --git a/djrill/tests/__init__.py b/djrill/tests/__init__.py index f0af178..910905a 100644 --- a/djrill/tests/__init__.py +++ b/djrill/tests/__init__.py @@ -4,3 +4,5 @@ from djrill.tests.test_mandrill_send import * from djrill.tests.test_mandrill_send_template import * from djrill.tests.test_mandrill_webhook import * from djrill.tests.test_mandrill_subaccounts import * + +from djrill.tests.test_mandrill_integration import * diff --git a/djrill/tests/test_mandrill_integration.py b/djrill/tests/test_mandrill_integration.py new file mode 100644 index 0000000..a949326 --- /dev/null +++ b/djrill/tests/test_mandrill_integration.py @@ -0,0 +1,88 @@ +from __future__ import unicode_literals +import os + +from django.core import mail +from django.test import TestCase + +from djrill import MandrillAPIError +from djrill.tests.utils import BackportedAssertions, override_settings + +try: + from unittest import skipUnless +except ImportError: + from django.utils.unittest import skipUnless + + +MANDRILL_TEST_API_KEY = os.getenv('MANDRILL_TEST_API_KEY') + + +@skipUnless(MANDRILL_TEST_API_KEY, + "Set MANDRILL_TEST_API_KEY environment variable to run integration tests") +@override_settings(MANDRILL_API_KEY=MANDRILL_TEST_API_KEY, + EMAIL_BACKEND="djrill.mail.backends.djrill.DjrillBackend") +class DjrillIntegrationTests(TestCase, BackportedAssertions): + """Mandrill API integration tests + + These tests run against the **live** Mandrill API, using the + environment variable `MANDRILL_TEST_API_KEY` as the API key. + If that variable is not set, these tests won't run. + + See https://mandrill.zendesk.com/hc/en-us/articles/205582447 + for info on Mandrill test keys. + + """ + + def setUp(self): + self.message = mail.EmailMultiAlternatives( + 'Subject', 'Text content', 'from@example.com', ['to@example.com']) + self.message.attach_alternative('

HTML content

', "text/html") + + def test_send_mail(self): + # Example of getting the Mandrill send status and _id from the message + sent_count = self.message.send() + self.assertEqual(sent_count, 1) + # noinspection PyUnresolvedReferences + response = self.message.mandrill_response + self.assertEqual(response[0]['status'], 'sent') # successful send (could still bounce later) + self.assertEqual(response[0]['email'], 'to@example.com') + self.assertGreater(len(response[0]['_id']), 0) + + def test_invalid_from(self): + # Example of trying to send from an invalid address + # Mandrill returns a 500 response (which raises a MandrillAPIError) + self.message.from_email = 'webmaster@localhost' # Django default DEFAULT_FROM_EMAIL + try: + self.message.send() + self.fail("This line will not be reached, because send() raised an exception") + except MandrillAPIError as err: + self.assertEqual(err.status_code, 500) + self.assertIn("email address is invalid", str(err)) + + def test_invalid_to(self): + # Example of detecting when a recipient is not a valid email address + self.message.to = ['invalid@localhost'] + sent_count = self.message.send() + self.assertEqual(sent_count, 1) # The send call is "successful"... + # noinspection PyUnresolvedReferences + response = self.message.mandrill_response + self.assertEqual(response[0]['status'], 'invalid') # ... but the mail is not delivered + + def test_rejected_to(self): + # Example of detecting when a recipient is on Mandrill's rejection blacklist + self.message.to = ['reject@test.mandrillapp.com'] + sent_count = self.message.send() + self.assertEqual(sent_count, 1) # The send call is "successful"... + # noinspection PyUnresolvedReferences + response = self.message.mandrill_response + self.assertEqual(response[0]['status'], 'rejected') # ... but the mail is not delivered + self.assertEqual(response[0]['reject_reason'], 'test') # ... and here's why + + @override_settings(MANDRILL_API_KEY="Hey, that's not an API key!") + def test_invalid_api_key(self): + # Example of trying to send with an invalid MANDRILL_API_KEY + try: + self.message.send() + self.fail("This line will not be reached, because send() raised an exception") + except MandrillAPIError as err: + self.assertEqual(err.status_code, 500) + self.assertIn("Invalid API key", str(err)) diff --git a/docs/contributing.rst b/docs/contributing.rst index a3e2a81..4e3bda5 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -42,8 +42,8 @@ Djrill is `tested on Travis `_ against sev combinations of Django and Python versions. (Full list in `.travis.yml `_.) -The included tests verify that Djrill constructs the expected Mandrill API -calls, without actually calling Mandrill or sending any email. So the tests +Most of the included tests verify that Djrill constructs the expected Mandrill API +calls, without actually calling Mandrill or sending any email. So these tests don't require a Mandrill API key, but they *do* require `mock `_ and `six `_ (``pip install mock six``). @@ -56,3 +56,9 @@ or:: python -Wall runtests.py + +If you set the environment variable `MANDRILL_TEST_API_KEY` to a valid Mandrill +`test API key`_, there are also a handful of integration tests which will run against +the live Mandrill API. (Otherwise these live API tests are skipped.) + +.. _test API key: https://mandrill.zendesk.com/hc/en-us/articles/205582447#test_key