web-dev-qa-db-fra.com

Comment puis-je tester les messages Django?

Dans mon application Django, j'essaie d'écrire un test unitaire qui exécute une action, puis vérifie les messages dans la réponse.

Autant que je sache, il n'y a pas de bonne façon de faire cela.

J'utilise la méthode de stockage CookieStorage, et j'aimerais faire quelque chose de similaire à ce qui suit:

    response = self.client.post('/do-something/', follow=True)
    self.assertEquals(response.context['messages'][0], "fail.")

Le problème est que tout ce que je reçois est un

print response.context['messages']
<Django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250>

Comment puis-je transformer cela en quelque chose d'utile ou est-ce que je le fais tout faux

Merci Daniel

62
dvydra

J'ai trouvé une approche vraiment facile:

response = self.client.post('/foo/')
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')

Si vous devez rechercher des messages dans une réponse sans contexte, vous pouvez utiliser les éléments suivants:

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')

Le stockage de secours ne prend pas en charge l’indexation, mais il s’agit d’un itératif. 

52
daveoncode

Cela fonctionne pour moi (affiche tous les messages):

print [m.message for m in list(response.context['messages'])]

Voici également quelques méthodes utilitaires que j'ai dans une classe de test héritée de TestCase de Django. Si vous préférez les avoir comme fonctions, supprimez les arguments self et remplacez self.fail() par 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)))
17
anttikoo

Depuis documentation Django :

En dehors des modèles, vous pouvez utiliser get_messages ()

Donc, vous pourriez écrire quelque chose comme:

from Django.contrib.messages import get_messages

[...]

messages = [m.message for m in get_messages(response.wsgi_request)]
self.assertIn('My message', messages)
9
moppag

Mettre à jour

Ma réponse originale a été écrite alors que Django était encore à 1,1 environ. Cette réponse n'est plus pertinente. Voir @ - daveoncode answer pour une meilleure solution.

Réponse originale

J'ai fait une expérience pour tester cela. J'ai modifié le paramètre MESSAGE_STORAGE dans l'un de mes projets en 'Django.contrib.messages.storage.cookie.CookieStorage' et exécuté un test écrit pour vérifier la présence de messages. Ça a marché. 

La principale différence avec ce que vous faisiez est la façon dont j'ai récupéré les messages. Voir ci-dessous:

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])

Ceci peut vaut la peine d'essayer.

3
Manoj Govindan

Version simplifiée de l'impasse:

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)
                )
0
Marco Fucci