Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

re-introduced auto clearing of mail.outbox #434

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -254,3 +254,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