Pytest-django: mail.outbox не устанавливается?

Созданный на 10 апр. 2018  ·  14Комментарии  ·  Источник: pytest-dev/pytest-django

Привет, спасибо за pytest-django! Цените всю тяжелую работу, использовал ее несколько раз без проблем.

У нас возникла небольшая загвоздка, когда мы обновили некоторые вещи, и внезапно mail.outbox не сохраняет электронные письма во время тестов. Я попытался выяснить, как именно использовать приспособление mailoutbox как описано здесь, но у меня возникли проблемы с его использованием.

Прямо сейчас мы тестируем в классе, и я пробовал довольно много конфигураций, чтобы передать mailoutbox fixture. Т.е. обновил ini:

[pytest]
usefixtures = mailoutbox

Не совсем уверен, как использовать это приспособление, но я попытался добавить позиционный аргумент mailoutbox в методы моего класса, но все еще не смог получить к нему доступ ... Я уверен, что мне не хватает чего-то простого.

Был бы признателен за толчок в правильном направлении - и еще раз большое спасибо за этот проект!

Самый полезный комментарий

Я думаю, что у меня такая же проблема, поэтому я решил сократить свой тест до базовой отправки электронной почты и запустил его индивидуально:

def test_reset_password(mailoutbox, db, settings):
    text_message = render_to_string('emails/password_reset/password_reset_successful.txt',
                                    context={})
    html_message = render_to_string('emails/password_reset/password_reset_successful.html',
                                    context={})
    subject = render_to_string('emails/password_reset/password_reset_successful_subject.txt',
                               context={})

    email = EmailMultiAlternatives(
        subject=subject,
        body=text_message,
        from_email="[email protected]",
        to=['[email protected]']
    )

    if html_message:
        email.attach_alternative(html_message, "text/html")
    email.send()

    print(settings.EMAIL_BACKEND)

    assert len(mailoutbox) == 1
>       assert len(mailoutbox) == 1
E       assert 0 == 1
E        +  where 0 = len([])

accounts/tests/api/test_reset_password.py:200: AssertionError
----------------------------------------------- Captured stdout call ------------------------------------------------
django.core.mail.backends.locmem.EmailBackend
--------------------------------------------- Captured stdout teardown ----------------------------------------------

Теперь самое интересное: если я удалю приспособление db , тест пройдёт. Итак, я попытался удалить свой метод django_db_setup , но безрезультатно ...

Я застрял в данный момент.

Все 14 Комментарий

См. Https://github.com/pytest-dev/pytest-django/blob/5da0935731d71aa347c57cd1753f51e3ba9f32d5/docs/helpers.rst#clearing -of-mailoutbox (7aee367).
(Не ясно, правильно ли я понимаю проблему)

Я думаю, что у меня такая же проблема, поэтому я решил сократить свой тест до базовой отправки электронной почты и запустил его индивидуально:

def test_reset_password(mailoutbox, db, settings):
    text_message = render_to_string('emails/password_reset/password_reset_successful.txt',
                                    context={})
    html_message = render_to_string('emails/password_reset/password_reset_successful.html',
                                    context={})
    subject = render_to_string('emails/password_reset/password_reset_successful_subject.txt',
                               context={})

    email = EmailMultiAlternatives(
        subject=subject,
        body=text_message,
        from_email="[email protected]",
        to=['[email protected]']
    )

    if html_message:
        email.attach_alternative(html_message, "text/html")
    email.send()

    print(settings.EMAIL_BACKEND)

    assert len(mailoutbox) == 1
>       assert len(mailoutbox) == 1
E       assert 0 == 1
E        +  where 0 = len([])

accounts/tests/api/test_reset_password.py:200: AssertionError
----------------------------------------------- Captured stdout call ------------------------------------------------
django.core.mail.backends.locmem.EmailBackend
--------------------------------------------- Captured stdout teardown ----------------------------------------------

Теперь самое интересное: если я удалю приспособление db , тест пройдёт. Итак, я попытался удалить свой метод django_db_setup , но безрезультатно ...

Я застрял в данный момент.

Я забыл упомянуть, что в том же проекте есть несколько тестов, где приспособление mailoutbox похоже, работает, поэтому я попытался определить разницу между этими тестами и неудачным.
Единственное отличие, которое я обнаружил, - это расположение аргумента mailoutbox в тестовой функции. Если это до какого-либо приспособления, которое зависит от приспособления db оно не работает, но оно работает, если я поставлю его после, так что я думаю, что нашел обходной путь.

Я могу подтвердить, что мы тоже наблюдаем такое поведение с pytest-django == 3.3.3.

@bogdanpetrea
Спасибо за исследование / обновление.
Будет полезно для кого-нибудь отладки / исправления этого.

Не уверен, действительно ли это связано, но я обнаружил, что может быть AttributeError из-за того, что mail.outbox не установлен в первую очередь, но это связано с изменением среды во время раскрутки pytest-django.
Ссылка: https://github.com/pytest-dev/pytest-django/pull/708

У меня сейчас проблема, этот почтовый ящик не пустой :(
Это последний аргумент тестовой функции.

РЕДАКТИРОВАТЬ: я вызываю mailoutbox.clear() перед реальным тестовым кодом как рабочий цикл.

@jedie
Можете ли вы предоставить воспроизводимый тестовый пример? Конечно, лучше всего будет неудачный тест для pytest-django.

Относится к # 708? (т.е. ткните по коду, которого он там касается)

Я создал тривиальный тестовый пример, который воспроизводит проблему (по крайней мере, так, как я ее испытываю): https://github.com/pytest-dev/pytest-django/compare/master...koniiiik : 589- mailoutbox-is-not-django-core-mail-outbox? expand = 1

Судя по тому, как я использовал mailoutbox , было бы также очень полезно иметь возможность иметь mailoutbox.clear() самом деле очищать как mailoutbox и mail.outbox . Если mailoutbox is mail.outbox , то кто-то может очистить папку "Исходящие" перед запуском кода, который затем должен генерировать определенное количество писем (например, 1 email).

Не уверен, связано ли это с этой проблемой, но фикстура mailoutbox не соответствует поведению mail.outbox в моем тесте. Это не сбор отправленных писем:

(Pdb) mail.outbox
[<django.core.mail.message.EmailMultiAlternatives object at 0x7f6d864cb198>]
(Pdb) mailoutbox
[]
(Pdb)

Не уверен, связано ли это с этой проблемой, но фикстура mailoutbox не соответствует поведению mail.outbox в моем тесте. Это не сбор отправленных писем:

(Pdb) mail.outbox
[<django.core.mail.message.EmailMultiAlternatives object at 0x7f6d864cb198>]
(Pdb) mailoutbox
[]
(Pdb)

Тем же.
mail.outbox содержит сообщение, а mailoutbox пусто.
Версия pytest-django - 3.9.0.

У меня такая же проблема.

Если я использую приспособление таким образом, это не сработает:

def test_send_foo_mail(mailoutbox, user_client, foo):

Вот так это работает:

def test_send_foo_mail(user_client, foo, mailoutbox):

Мне потребовалось много времени, чтобы это открыть. Я хотел бы помочь отладить это. Я посмотрел на реализацию, но понятия не имею, как это отладить.

Связанный: https://stackoverflow.com/questions/66846621/mailoutbox-works-only-if-last-fixture

Испытывает то же поведение, что и предыдущий комментатор. Использование его таким образом не работает:

def test_command_and_email(
    mailoutbox, argument, time_machine, mocker 
):

Но все работает как exe, если просто поставить на последнее место.

def test_command_and_email(
    argument, time_machine, mocker, mailoutbox
):

Аргумент argument также является приспособлением, которое использует приспособление db , так что я предполагаю, что это основная причина такого поведения.
Я использую pytets-django 4.3.0

Была ли эта страница полезной?
0 / 5 - 0 рейтинги