webentwicklung-frage-antwort-db.com.de

Wie kann ich Django-Nachrichten Unit-testen?

In meiner Django-Anwendung versuche ich, einen Komponententest zu schreiben, der eine Aktion ausführt und dann die Nachrichten in der Antwort überprüft.

Soweit ich das beurteilen kann, gibt es dafür keinen guten Weg.

Ich verwende die CookieStorage-Speichermethode und möchte Folgendes tun:

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

Das Problem ist, alles was ich zurück bekomme, ist a

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

Wie kann ich daraus etwas Nützliches machen oder mache ich alles falsch?

Danke, Daniel

62
dvydra

Ich habe einen wirklich einfachen Ansatz gefunden:

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

Wenn Sie in einer Antwort ohne Kontext nach Nachrichten suchen müssen, können Sie Folgendes verwenden:

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

Der Fallback-Speicher unterstützt keine Indizierung, ist jedoch iterierbar. 

52
daveoncode

Das funktioniert für mich (zeigt alle Nachrichten an):

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

Hier sind auch einige Hilfsmethoden, die ich in einer Testklasse habe, die von Django's TestCase übernommen wurde. Wenn Sie sie lieber als Funktionen verwenden möchten, entfernen Sie die self-Argumente und ersetzen Sie self.fail() durch eine 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

Aus Django Dokumentation :

Außerhalb von Vorlagen können Sie get_messages () verwenden.

So könnte man so etwas schreiben:

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

Aktualisieren

Meine ursprüngliche Antwort wurde geschrieben, als Django noch etwa 1,1 war. Diese Antwort ist nicht mehr relevant. Siehe @ daveoncode answer für eine bessere Lösung.

Ursprüngliche Antwort

Ich habe ein Experiment gemacht, um das zu testen. Ich änderte die Einstellung MESSAGE_STORAGE in einem meiner Projekte in 'Django.contrib.messages.storage.cookie.CookieStorage' und führte einen Test aus, den ich geschrieben hatte, um nach Nachrichten zu suchen. Es funktionierte. 

Der Hauptunterschied zu dem, was Sie getan haben, ist die Art, wie ich Nachrichten abrief. Siehe unten:

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

Dies kann einen Versuch wert sein.

3
Manoj Govindan

Einfachere Version der Pattsituation:

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