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 etwas Ähnliches wie das Folgende 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
python
django
unit-testing
django-testing
dvydra
quelle
quelle
assert_has_message(response, msg_text)
und ihn überall dort zu verwenden, wo Sie möchten. Wenn Sie einen besseren Weg finden, um auf die Nachrichten zuzugreifen, ändern Sie die Funktion einfach an einer Stelle.messages_list = CookieStorage(response)._decode(response.cookies['messages'].value)
Hiermit erhalten Sie eine Liste der Objekte django.contrib.messages.storage.base.Message.Antworten:
Ich fand einen wirklich einfachen Ansatz:
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.
quelle
self.assertEqual(m[0].message, 'my message')
funktioniertlist(r.wsgi_request._messages)
*** TypeError: 'FallbackStorage' object does not support indexing
. Es ist jedoch ein Iterable und Sie können jedesfor m in messages
Konstrukt verwenden.dir()
in einem interaktiven Debugger (import ipdb; ipdb.set_trace()
) in einem Testfall.Dies funktioniert bei mir (zeigt alle Nachrichten an):
print [m.message for m in list(response.context['messages'])]
Hier sind auch einige Dienstprogrammmethoden, die ich in einer Testklasse habe, die von Djangos TestCase geerbt wurde. Wenn Sie sie lieber als Funktionen haben möchten, entfernen Sie die
self
Argumente und ersetzen Sie sieself.fail()
durch araise
.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)))
quelle
Von Django-Dokumentation :
Sie könnten also so etwas schreiben wie:
from django.contrib.messages import get_messages [...] messages = [m.message for m in get_messages(response.wsgi_request)] self.assertIn('My message', messages)
quelle
Aktualisieren
Meine ursprüngliche Antwort wurde geschrieben, als Django noch ungefähr 1.1 war. Diese Antwort ist nicht mehr relevant. Siehe die Antwort von @ daveoncodeEine bessere Lösung finden .
Ursprüngliche Antwort
Ich habe ein Experiment durchgeführt, um dies zu testen. Ich habe die
MESSAGE_STORAGE
Einstellung in einem meiner Projekte in geändert'django.contrib.messages.storage.cookie.CookieStorage'
und einen Test ausgeführt, den ich geschrieben habe, um nach Nachrichten zu suchen. Es funktionierte.Der Hauptunterschied zu dem, was Sie getan haben, ist die Art und Weise, wie ich Nachrichten abgerufen habe. 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.
quelle
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) )
quelle
Testen Sie die Helfer zur Überprüfung der Anzahl und des Inhalts der Antwortnachrichten
def get_response_messages(self, response): from django.contrib.messages import get_messages return list(get_messages(response.wsgi_request)) def check_response_messages(self, response, message_index=None, message_value=None, exp_count=None): messages = self.get_response_messages(response) if exp_count is not None: self.assertEqual(len(messages), exp_count) if message_index is not None: message = messages[message_index] self.assertIn(message_value, str(message))
Kann so verwendet werden
message_value = "You can not switch to another type of account" self.check_response_messages(response, exp_count=1, message_index=0, message_value=message_value)
quelle