Python / Django: як стверджувати, що результат модульного тесту містить певний рядок?


79

У модульному тесті python (насправді Django), яке правильне assertтвердження підкаже мені, чи мій результат тесту містить рядок, який я вибрав?

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

Я хочу переконатися, що мій resultмістить щонайменше об'єкт json (або рядок), який я вказав як другий аргумент вище

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

Відповіді:


66
self.assertContains(result, "abcd")

Ви можете змінити його для роботи з json.

Використовуйте self.assertContainsлише для HttpResponseпредметів. Для інших об’єктів використовуйте self.assertIn.


2
так, але завдяки структурі json, у неї може бути додано пробіли, які не є проблематичними в json, але є проблематичними, якщо ви хочете порівняти з рядком python.
Франсуа

33
assertContains не призначений для використання для іншого об'єкта, ніж HttpReponse, віддайте перевагу використанню assertTrue з ключовим словом python "in" (див. мій answser нижче).
П'єр Кріулансі

12
Це неправильно. Assertconains призначений для http-відповідей.
kagronick

3
Ця відповідь повинна пояснити, що вона призначена лише для HttpResponse
rtindru

123

Щоб стверджувати, чи є рядок підрядком іншого чи ні, слід використовувати assertInі assertNotIn:

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

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

Вони нові після Python 2.7 та Python 3.1


5
Також assertInнадає корисні повідомлення про помилку, як ви проілюстрували.
jamesc

22

Ви можете написати твердження про очікувану частину рядка в іншому рядку за допомогою простого ключового слова assertTrue + у python:

self.assertTrue("expected_part_of_string" in my_longer_string)

9
Проблема цієї стратегії полягає в тому, що це може давати погані повідомлення про помилки у формі "AssertionError: False is not true"
jamesc

1
@jamesc погоджується з вами, тест повинен показати деталі помилок, будь-яке вирішення цієї проблеми, якщо використовується assertTrue?
Лук Арон,

@LukAron Якщо вам потрібно використовувати assertTrue, ви можете передати повідомлення, яке ви побудували заздалегідь, щоб містити докладнішу інформацію: assertTrue (expr, msg = message). Якщо повідомлення ускладнюється, тоді ви можете витягти будівлю повідомлення та перевірити assertTrue в окремий помічник твердження, який може мати власні тести, щоб переконатись, що він поводиться належним чином.
jamesc

9

Створіть об'єкт JSON за допомогою json.dumps().

Потім порівняйте їх за допомогою 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)

1
Чому використовувати assertTrue()замість assertEqual()? Принаймні assertEqual(), модуль буде друкувати як результат, так і очікувані значення.
Denilson Sá Maia

Ви маєте рацію, краще assertEqual (). Я не можу знайти посилання, але я був упевнений, що десь читав, щоб використовувати assertTrue замість assertEqual. Очевидно, я помилився :) Я виправлю приклад вище.
Вінсент Одеберт,

12
Зауважте, що це буде ненадійно, якщо у вас є більше одного ключа в будь-якому словнику, оскільки dumps()використовується довільне впорядкування, і ми не знаємо порядку введення ключів result. Вам було б набагато краще використовувати self.assertEqual(json.loads(result), expected_dict).
Андре Карон,

7

Як згадував Ед I , assertInце, мабуть, найпростіша відповідь на пошук одного рядка в іншому. Однак питання говорить:

Я хочу переконатися, що мій resultмістить щонайменше об'єкт json (або рядок), який я вказав як другий аргумент вище, тобто{"car" : ["toyota","honda"]}

Тому я б використовував декілька тверджень, щоб корисні повідомлення отримувались при відмові - тести повинні бути зрозумілі та підтримувані в майбутньому, можливо, тим, хто їх не писав спочатку. Тому припускаючи, що ми перебуваємо всередині 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'])

Що дає такі корисні повідомлення:

# 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']

-2

Я потрапив у подібну проблему і використав атрибут rendered_content , тому написав

assertTrue('string' in response.rendered_content) і так само

assertFalse('string' in response.rendered_content) якщо я хочу перевірити, що рядок не відображається

Але це також спрацювало за ранньо запропонованим методом,

AssertContains(response, 'html string as rendered')

Тому я б сказав, що перший з них є більш простим. Сподіваюся, це допоможе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.