Olá, obrigado por pytest-django! Aprecie todo o trabalho árduo, usei-o algumas vezes sem problemas.
Estamos enfrentando um problema quando atualizamos algumas coisas e de repente mail.outbox
não está retendo e-mails durante os testes. Tentei descobrir como usar exatamente o fixture mailoutbox
conforme documentado aqui, mas estou tendo problemas para usar isso.
No momento, estamos testando em uma classe e tentei algumas configurações para aprovar mailoutbox
fixture. Ou seja, eu atualizei o ini:
[pytest]
usefixtures = mailoutbox
Não tenho certeza de como usar aquele acessório, porém, tentei adicionar o argumento posicional mailoutbox
aos meus métodos de classe, ainda não consegui acessá-lo .. Tenho certeza de que estou perdendo algo simples.
Agradeceria um empurrão na direção certa - e novamente, muito obrigado por este projeto!
Consulte https://github.com/pytest-dev/pytest-django/blob/5da0935731d71aa347c57cd1753f51e3ba9f32d5/docs/helpers.rst#clearing -of-mailoutbox (7aee367).
(Não está claro se eu entendi o problema corretamente)
Acho que estou tendo o mesmo problema, então decidi reduzir meu teste para um envio de e-mail básico e executá-lo individualmente:
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 ----------------------------------------------
Agora, a parte legal é que, se eu remover o acessório db
, o teste passa. Tentei excluir meu método django_db_setup
, mas sem sucesso ...
Estou preso no momento.
Esqueci de mencionar que existem alguns testes, no mesmo projeto, onde o fixture mailoutbox
parece funcionar, então tentei detectar alguma diferença entre esses testes e o que falhou.
A única diferença que encontrei é o posicionamento do argumento mailoutbox
na função de teste. Se for antes de qualquer acessório que dependa do acessório db
, ele não funcionará, mas funcionará se eu colocá-lo depois, então acho que encontrei uma solução alternativa.
Posso confirmar que estamos vendo esse comportamento também com pytest-django == 3.3.3
@bogdanpetrea
Obrigado pela investigação / atualização.
Será útil para alguém que está depurando / corrigindo isso.
Não tenho certeza se está realmente relacionado, mas descobri que pode haver um AttributeError devido a mail.outbox
não ter sido definido em primeiro lugar - mas isso está relacionado à mudança de ambiente enquanto o pytest-django gira.
Ref: https://github.com/pytest-dev/pytest-django/pull/708
Atualmente, tenho o problema, essa caixa de correio não está vazia :(
É o último argumento da função de teste.
EDIT: Eu chamo mailoutbox.clear()
antes do código de teste real como work-a-round.
@jedie
Você pode fornecer um caso de teste reproduzível? Um teste de falha para pytest-django seria o melhor, é claro.
Relacionado a # 708? (ou seja, vasculhe o código que ele toca lá)
Eu criei um caso de teste trivial que reproduz o problema (pelo menos do jeito que estou passando): https://github.com/pytest-dev/pytest-django/compare/master...koniiiik : 589- mailoutbox-is-not-django-core-mail-outbox? expand = 1
Da forma como usei mailoutbox
, também seria muito útil poder fazer mailoutbox.clear()
realmente limpar mailoutbox
e mail.outbox
. Se mailoutbox is mail.outbox
, então alguém poderia limpar a caixa de saída antes de executar o código que deveria gerar um número específico de e-mails (por exemplo, 1
e-mail).
Não tenho certeza se isso está relacionado a este problema, mas o fixture mailoutbox
não corresponde ao comportamento de mail.outbox
em meu teste. Não está coletando e-mails enviados:
(Pdb) mail.outbox
[<django.core.mail.message.EmailMultiAlternatives object at 0x7f6d864cb198>]
(Pdb) mailoutbox
[]
(Pdb)
Não tenho certeza se isso está relacionado a este problema, mas o fixture
mailoutbox
não corresponde ao comportamento demail.outbox
em meu teste. Não está coletando e-mails enviados:(Pdb) mail.outbox [<django.core.mail.message.EmailMultiAlternatives object at 0x7f6d864cb198>] (Pdb) mailoutbox [] (Pdb)
Mesmo.
mail.outbox
contém uma mensagem enquanto mailoutbox
está vazio.
A versão do pytest-django é 3.9.0.
Eu tenho o mesmo problema.
Se eu usar o acessório assim, ele falhará:
def test_send_foo_mail(mailoutbox, user_client, foo):
Assim funciona:
def test_send_foo_mail(user_client, foo, mailoutbox):
Levei muito tempo para descobri-lo. Eu gostaria de ajudar a depurar isso. Eu olhei para a implementação, mas não tenho ideia de como depurar isso.
Relacionado: https://stackoverflow.com/questions/66846621/mailoutbox-works-only-if-last-fixture
Experimentando o mesmo comportamento do comentarista anterior. Usar assim não funciona:
def test_command_and_email(
mailoutbox, argument, time_machine, mocker
):
Mas tudo funciona como esperado se eu apenas colocá-lo no último lugar.
def test_command_and_email(
argument, time_machine, mocker, mailoutbox
):
O argumento argument
também é um fixture que usa o fixture db
, então acho que essa é a principal razão deste comportamento.
Estou usando pytets-django 4.3.0
Comentários muito úteis
Acho que estou tendo o mesmo problema, então decidi reduzir meu teste para um envio de e-mail básico e executá-lo individualmente:
Agora, a parte legal é que, se eu remover o acessório
db
, o teste passa. Tentei excluir meu métododjango_db_setup
, mas sem sucesso ...Estou preso no momento.