python - template - ¿Cómo puedo probar los mensajes de django por unidad?
django template variable (5)
Actualizar
Mi respuesta original fue escrita cuando django todavía era 1.1 o más. Esta respuesta ya no es relevante. Ver la answer @ daveoncode para una mejor solución.
Respuesta original
Hice un experimento para probar esto. Cambié la configuración de MESSAGE_STORAGE
en uno de mis proyectos a ''django.contrib.messages.storage.cookie.CookieStorage''
y ''django.contrib.messages.storage.cookie.CookieStorage''
una prueba que había escrito para verificar si había mensajes. Funcionó.
La diferencia clave de lo que estabas haciendo es la forma en que recuperé los mensajes. Vea abajo:
def test_message_sending(self):
data = dict(...)
response = self.client.post(reverse(''my_view''), data)
messages = self.user.get_and_delete_messages()
self.assertTrue(messages)
self.assertEqual(''Hey there!'', messages[0])
Esto puede valer la pena intentarlo.
En mi aplicación django, intento escribir una prueba unitaria que realiza una acción y luego verifico los mensajes en la respuesta.
Por lo que puedo decir, no hay una buena manera de hacer esto.
Estoy usando el método de almacenamiento CookieStorage, y me gustaría hacer algo similar a lo siguiente:
response = self.client.post(''/do-something/'', follow=True)
self.assertEquals(response.context[''messages''][0], "fail.")
El problema es que todo lo que recupero es una
print response.context[''messages'']
<django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250>
¿Cómo puedo convertir esto en algo útil, o lo estoy haciendo todo mal?
Gracias, Daniel
De la documentación de django :
Fuera de las plantillas, puedes usar get_messages ()
Entonces, podrías escribir algo como:
from django.contrib.messages import get_messages
[...]
messages = [m.message for m in get_messages(response.wsgi_request)]
self.assertIn(''My message'', messages)
Encontré un enfoque realmente fácil:
response = self.client.post(''/foo/'')
messages = list(response.context[''messages''])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), ''my message'')
Si necesita verificar los mensajes en una respuesta que no tiene contexto, puede usar lo siguiente:
from django.contrib.messages import get_messages
messages = list(get_messages(response.wsgi_request))
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), ''my message'')
El almacenamiento alternativo no es compatible con la indexación, sin embargo, es iterable.
Esto funciona para mí (muestra todos los mensajes):
print [m.message for m in list(response.context[''messages''])]
También aquí hay un par de métodos de utilidad que tengo en una clase de prueba heredada de TestCase de Django. Si prefiere tenerlos como funciones, elimine los argumentos self.fail()
y reemplace self.fail()
con un raise
.
def assert_message_count(self, response, expect_num):
"""
Asserts that exactly the given number of messages have been sent.
"""
actual_num = len(response.context[''messages''])
if actual_num != expect_num:
self.fail(''Message count was %d, expected %d'' %
(actual_num, expect_num))
def assert_message_contains(self, response, text, level=None):
"""
Asserts that there is exactly one message containing the given text.
"""
messages = response.context[''messages'']
matches = [m for m in messages if text in m.message]
if len(matches) == 1:
msg = matches[0]
if level is not None and msg.level != level:
self.fail(''There was one matching message but with different''
''level: %s != %s'' % (msg.level, level))
return
elif len(matches) == 0:
messages_str = ", ".join(''"%s"'' % m for m in messages)
self.fail(''No message contained text "%s", messages were: %s'' %
(text, messages_str))
else:
self.fail(''Multiple messages contained text "%s": %s'' %
(text, ", ".join((''"%s"'' % m) for m in matches)))
def assert_message_not_contains(self, response, text):
""" Assert that no message contains the given text. """
messages = response.context[''messages'']
matches = [m for m in messages if text in m.message]
if len(matches) > 0:
self.fail(''Message(s) contained text "%s": %s'' %
(text, ", ".join((''"%s"'' % m) for m in matches)))
Una versión más simple del punto muerto:
class TestCaseMessagesMixture(object):
def assertMessageCount(self, response, expect_num):
"""
Asserts that exactly the given number of messages have been sent.
"""
actual_num = len(response.context[''messages''])
if actual_num != expect_num:
self.fail(''Message count was %d, expected %d'' %
(actual_num, expect_num)
)
def assertMessageEqual(self, response, text):
"""
Asserts that the response includes the message text.
"""
messages = [m.message for m in response.context[''messages'']]
if text not in messages:
self.fail(
''No message with text "%s", messages were: %s'' %
(text, messages)
)
def assertMessageNotEqual(self, response, text):
"""
Asserts that the response does not include the message text.
"""
messages = [m.message for m in response.context[''messages'']]
if text in messages:
self.fail(
''Message with text "%s" found, messages were: %s'' %
(text, messages)
)