Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
re-introduced auto clearing of mail.outbox (pytest-dev#434)
Browse files Browse the repository at this point in the history
  • Loading branch information
peterlauri authored and mfa committed May 17, 2017
1 parent b77c16e commit c71e959
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 63 deletions.
11 changes: 11 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Changelog
=========

3.1.2
-----

Bug fixes
^^^^^^^^^

* Auto clearing of ``mail.outbox`` has been re-introduced to not break
functionality in 3.x.x release. This means that Compatibility issues
mentioned in the 3.1.0 release are no longer present. Related issue:
_`pytest-django issue <https://github.com/pytest-dev/pytest-django/issues/433>`

3.1.1
-----

Expand Down
8 changes: 8 additions & 0 deletions docs/helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,11 @@ Clearing of site cache
If ``django.contrib.sites`` is in your INSTALLED_APPS, Site cache will
be cleared for each test to avoid hitting the cache and cause wrong Site
object to be returned by ``Site.objects.get_current()``.


Clearing of mail.outbox
~~~~~~~~~~~~~~~~~~~~~~~

``mail.outbox`` will be cleared for each pytest, to give tests a empty
mailbox. It is however more pytestic to use the ``mailoutbox`` fixture
to access ``mail.outbox``.
32 changes: 5 additions & 27 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,44 +415,22 @@ def teardown():
request.addfinalizer(teardown)


class _DirectMailboxAccessProtector(list):

def _raise_assertion(*args, **kwargs):
__tracebackhide__ = True
raise AssertionError('''To access mail.outbox, use the mailoutbox fixture.
See http://pytest-django.readthedocs.io/en/latest/helpers.html#mailoutbox for more information.''')

__len__ = _raise_assertion
__getitem__ = _raise_assertion
__nonzero__ = _raise_assertion
__bool__ = _raise_assertion
__eq__ = _raise_assertion
__ne__ = _raise_assertion
__iter__ = _raise_assertion


@pytest.fixture(autouse=True)
def _error_on_direct_mail_outbox_access(monkeypatch):
@pytest.fixture(scope='function', autouse=True)
def _dj_autoclear_mailbox():
if not django_settings_is_configured():
return

from django.core import mail

outbox = _DirectMailboxAccessProtector()
monkeypatch.setattr(mail, 'outbox', outbox)
return outbox
del mail.outbox[:]


@pytest.fixture(scope='function')
def mailoutbox(monkeypatch, _error_on_direct_mail_outbox_access):
def mailoutbox(monkeypatch, _dj_autoclear_mailbox):
if not django_settings_is_configured():
return

from django.core import mail

outbox = list()
monkeypatch.setattr(mail, 'outbox', outbox)
return outbox
return mail.outbox


@pytest.fixture(autouse=True, scope='function')
Expand Down
47 changes: 11 additions & 36 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,17 @@
# This is possible with some of the testdir magic, but this is the lazy way
# to do it.


class Test_direct_mailbox_access_not_allowed():

def test_len(self):
with pytest.raises(AssertionError):
len(mail.outbox)

def test_indexing(self):
with pytest.raises(AssertionError):
mail.outbox[0]

def test_bool(self):
with pytest.raises(AssertionError):
if mail.outbox:
pass

def test_equality(self):
with pytest.raises(AssertionError):
mail.outbox == 'whatever'

def test_not_equality(self):
with pytest.raises(AssertionError):
mail.outbox != 'whatever'

def test_unpacking(self):
with pytest.raises(AssertionError):
(foo,) = mail.outbox

def test_iteration(self):
with pytest.raises(AssertionError):
for x in mail.outbox:
pass


def test_direct_mailbox_proection_should_not_break_sending_mail():
mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com'])
@pytest.mark.parametrize('subject', ['subject1', 'subject2'])
def test_autoclear_mailbox(subject):
assert len(mail.outbox) == 0
mail.send_mail(subject, 'body', 'from@example.com', ['to@example.com'])
assert len(mail.outbox) == 1

m = mail.outbox[0]
assert m.subject == subject
assert m.body == 'body'
assert m.from_email == 'from@example.com'
assert m.to == ['to@example.com']


class TestDirectAccessWorksForDjangoTestCase(TestCase):
Expand Down

0 comments on commit c71e959

Please sign in to comment.