Django アプリケーションが正しい内容の電子メールを送信することをテストする必要があります。実際の電子メール サービスをテストしていないため、外部システム (アドホックのGmailアカウントなど) に依存したくありません...
おそらく、電子メールを送信時にフォルダー内にローカルに保存したいと思います。それを達成する方法に関するヒントはありますか?
Django テスト フレームワークには、電子メール サービスのテストを支援するヘルパーが組み込まれています。
ドキュメントからの例 (短いバージョン):
from django.core import mail
from django.test import TestCase
class EmailTest(TestCase):
def test_send_email(self):
mail.send_mail('Subject here', 'Here is the message.',
'from@example.com', ['to@example.com'],
fail_silently=False)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, 'Subject here')
電子メールの送信にファイル バックエンドを使用できます。これは、開発とテストにとって非常に便利なソリューションです。メールは送信せず、指定できるフォルダに保存!
単体テストを行う場合、最善の解決策は、django が提供するインメモリ バックエンドを使用することです。
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
py.testフィクスチャとして使用する場合を考えてみましょう
@pytest.fixture(autouse=True)
def email_backend_setup(self, settings):
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
各テストではmail.outbox
、サーバーで がリセットされるため、テスト間の副作用はありません。
from django.core import mail
def test_send(self):
mail.send_mail('subject', 'body.', 'from@example.com', ['to@example.com'])
assert len(mail.outbox) == 1
def test_send_again(self):
mail.send_mail('subject', 'body.', 'from@example.com', ['to@example.com'])
assert len(mail.outbox) == 1
MailHogを使用する
MailCatcher にインスパイアされ、簡単にインストールできます。
Go で構築 - MailHog は複数のプラットフォームでインストールせずに実行されます。
また、 Jimと呼ばれるコンポーネント、MailHog Chaos Monkeyがあり、さまざまな問題が発生している電子メールの送信をテストできます。
ジムは何ができますか?
- 接続を拒否する
- レート制限接続
- 認証を拒否する
- 送信者を拒否
- 受信者を拒否
詳しくはこちらをご覧ください。
( UTF-8 でエンコードされた絵文字を含むメールを送信するときに失敗した元の mailcatcher とは異なり、現在のリリースでは実際には修正されていませんが、MailHog は機能します。)
添付ファイルの送信を必要としないプロジェクトでは、django-mailerを使用します。これには、送信をトリガーするまですべての送信メールがキューに入れられるという利点があり、送信された後でもログに記録されます-これらはすべて管理画面に表示されるため、メール送信コードがインターチューブに送信しようとしているものをすばやく簡単に確認できます。
Django には、メモリ内メール バックエンドもあります。詳しくは、インメモリ バックエンドのドキュメントを参照してください。これは Django 1.6 に存在しますが、それ以前に存在するかどうかはわかりません。
テスト目的で SMTPLib にパッチを適用すると、メールを送信せずに送信をテストするのに役立ちます。
inherit fromsmtpd.SMTPServer
と を使用して、独自の非常に単純な SMTP サーバーを起動してみませんかthreading.Thread
。
class TestingSMTPServer(smtpd.SMTPServer, threading.Thread):
def __init__(self, port=25):
smtpd.SMTPServer.__init__(
self,
('localhost', port),
('localhost', port),
decode_data=False
)
threading.Thread.__init__(self)
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
self.received_peer = peer
self.received_mailfrom = mailfrom
self.received_rcpttos = rcpttos
self.received_data = data
def run(self):
asyncore.loop()
process_message は、SMTP サーバーがメール リクエストを受信するたびに呼び出されます。ここでは、好きなことを行うことができます。
テスト コードで、次のようにします。
smtp_server = TestingSMTPServer()
smtp_server.start()
do_thing_that_would_send_a_mail()
smtp_server.close()
self.assertIn(b'hello', smtp_server.received_data)
asyncore ループを終了するために呼び出すことを忘れないでください (サーバーのリッスンを停止しclose()
ますasyncore.dispatcher
) 。smtp_server.close()