Python / Django: Wie kann man behaupten, dass das Unit-Testergebnis eine bestimmte Zeichenfolge enthält?

78

Was ist in einem Python-Unit-Test (eigentlich Django) die richtige assertAussage, die mir sagt, ob mein Testergebnis eine Zeichenfolge meiner Wahl enthält?

self.assertContainsTheString(result, {"car" : ["toyota","honda"]})

Ich möchte sicherstellen, dass my resultmindestens das json-Objekt (oder die Zeichenfolge) enthält, das ich oben als zweites Argument angegeben habe

{"car" : ["toyota","honda"]}
user798719
quelle

Antworten:

64
self.assertContains(result, "abcd")

Sie können es so ändern, dass es mit json funktioniert.

Verwenden Sie self.assertContainsnur für HttpResponseObjekte. Verwenden Sie für andere Objekte self.assertIn.

Akshar Raaj
quelle
2
Ja, aber aufgrund der JSON-Struktur können einige Leerzeichen hinzugefügt werden, die in JSON nicht problematisch sind, aber problematisch, wenn Sie mit einer Python-Zeichenfolge vergleichen möchten.
François
32
assertContains soll nicht für andere Objekte als HttpReponse verwendet werden. Verwenden Sie stattdessen assertTrue mit dem Python-Schlüsselwort "in" (siehe meine Antwort unten).
Pierre Criulanscy
12
Das ist falsch. Assertconains ist für http-Antworten.
Kagronick
3
Diese Antwort sollte klarstellen, dass sie nur für HttpResponse zugeschnitten ist
rtindru
121

Zu, wenn ein String ist oder nicht , eine Teil eines anderen, sollten Sie verwenden assertInund assertNotIn:

# Passes
self.assertIn('bcd', 'abcde')

# AssertionError: 'bcd' unexpectedly found in 'abcde'
self.assertNotIn('bcd', 'abcde')

Diese sind seit Python 2.7 und Python 3.1 neu

Ed I.
quelle
5
Auch assertInhilfreiche Nachrichten bei einem Fehler , wie Sie dargestellt haben.
Jamesc
22

Sie können eine Zusicherung über den erwarteten Teil eines Strings in einen anderen String mit einem einfachen assertTrue + in Python-Schlüsselwort schreiben:

self.assertTrue("expected_part_of_string" in my_longer_string)
Pierre Criulanscy
quelle
9
Das Problem bei dieser Strategie ist, dass schlechte
Fehlermeldungen
1
@jamesc stimme dir zu, Test sollte die Fehlerdetails anzeigen, eine Problemumgehung für dieses Problem, wenn assertTrue verwendet wird?
Luk Aron
@LukAron Wenn Sie assertTrue verwenden müssen, können Sie eine Nachricht übergeben, die Sie zuvor erstellt haben, um weitere Details zu enthalten: assertTrue (Ausdruck, msg = Nachricht). Wenn die Nachricht kompliziert wird, können Sie den Nachrichtenaufbau und die assertTrue-Prüfung in einen separaten Assertion-Helfer extrahieren, der möglicherweise eigene Tests hat, um sicherzustellen, dass er sich wie erwartet verhält.
Jamesc
9

Erstellen Sie ein JSON-Objekt mit json.dumps().

Dann vergleichen Sie sie mit assertEqual(result, your_json_dict)

import json

expected_dict = {"car":["toyota", "honda"]}
expected_dict_json = json.dumps(expected_dict)

self.assertEqual(result, expected_dict_json)
Vincent Audebert
quelle
1
Warum verwenden assertTrue()statt assertEqual()? Zumindest mit assertEqual()druckt das Modul sowohl das Ergebnis als auch die erwarteten Werte.
Denilson Sá Maia
Sie haben Recht, assertEqual () ist besser. Ich kann den Link nicht finden, war mir aber ziemlich sicher, dass ich irgendwo gelesen habe, um assertTrue anstelle von assertEqual zu verwenden. Offensichtlich habe ich mich geirrt :) Ich werde das obige Beispiel korrigieren.
Vincent Audebert
12
Beachten Sie, dass dies unzuverlässig ist, wenn Sie mehr als einen Schlüssel in einem Wörterbuch haben, da dies dumps()eine willkürliche Reihenfolge verwendet und wir die Reihenfolge der Schlüssel in nicht kennen result. Sie wären viel besser dran self.assertEqual(json.loads(result), expected_dict).
André Caron
6

Wie von Ed I erwähnt , assertInist dies wahrscheinlich die einfachste Antwort, um eine Zeichenfolge in einer anderen zu finden. Die Frage lautet jedoch:

Ich möchte sicherstellen, dass my resultmindestens das json-Objekt (oder die Zeichenfolge) enthält, das ich als zweites Argument oben angegeben habe, d. H.{"car" : ["toyota","honda"]}

Daher würde ich mehrere Behauptungen verwenden, damit bei einem Fehler hilfreiche Nachrichten empfangen werden. Tests müssen in Zukunft verstanden und gepflegt werden, möglicherweise von jemandem, der sie ursprünglich nicht geschrieben hat. Nehmen wir also an, wir befinden uns in einem django.test.TestCase:

# Check that `car` is a key in `result`
self.assertIn('car', result)
# Compare the `car` to what's expected (assuming that order matters)
self.assertEqual(result['car'], ['toyota', 'honda'])

Welches gibt hilfreiche Nachrichten wie folgt:

# If 'car' isn't in the result:
AssertionError: 'car' not found in {'context': ..., 'etc':... }
# If 'car' entry doesn't match:
AssertionError: Lists differ: ['toyota', 'honda'] != ['honda', 'volvo']

First differing element 0:
toyota
honda

- ['toyota', 'honda']
+ ['honda', 'volvo']
jamesc
quelle
-2

Ich befand mich in einem ähnlichen Problem und benutzte das Attribut render_content , also schrieb ich

assertTrue('string' in response.rendered_content) und ähnlich

assertFalse('string' in response.rendered_content) wenn ich testen möchte, dass eine Zeichenfolge nicht gerendert wird

Aber es funktionierte auch die früh vorgeschlagene Methode,

AssertContains(response, 'html string as rendered')

Also würde ich sagen, dass der erste einfacher ist. Ich hoffe es wird helfen.

tombishop83
quelle