Якщо ви повинні мати лише одне твердження за тест; як перевірити кілька входів?


15

Я намагаюся створити кілька тестових випадків і прочитав, що вам слід спробувати обмежити кількість тверджень на тестовий випадок.

Отже, моє запитання полягає в тому, який найкращий спосіб розпочати тестування функції з кількома входами. Наприклад, у мене є функція, яка розбирає рядок від користувача і повертає кількість хвилин. Рядок може бути у формі "5w6h2d1m", де w, h, d, mвідповідають кількості тижнів, годин, днів і хвилин.

Якби я хотів дотримуватися "1 твердження за тестовим правилом", я повинен був би зробити кілька тестів для кожного варіанта введення? Це здається нерозумним, тому натомість у мене просто є щось на кшталт:

self.assertEqual(parse_date('5m'), 5)
self.assertEqual(parse_date('5h'), 300)
self.assertEqual(parse_date('5d') ,7200)
self.assertEqual(parse_date('1d4h20m'), 1700)

В одному тестовому випадку. Чи є кращий спосіб?


Найкращий спосіб зробити це за допомогою параметрів (деякі рамки підтримують цю функцію, всі рамки повинні). Таким чином ви випробовуєте одну поведінку, але враховуючи багато тестових випадків і все ще можете побачити, які значення параметрів спричинили помилку, якщо сталася помилка
Kemoda

Відповіді:


23

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

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

Ви повинні реалізовувати свої судження в кожному конкретному випадку, щоб перевірити, чи не краще ви тестувати єдину концепцію з декількома твердженнями чи мати одне твердження у багатьох тестах.

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


17

Це дуже залежить від вашої бібліотеки тестування. У бібліотеці C # NUnit ви можете зробити щось на кшталт:

[TestCase('5m', 5)]
[TestCase('5h', 300)]
[TestCase('5d', 7200)]
[TestCase('1d4h20m', 1700)]
public void ParseDateTest(inputString, expectedMinutes)
{
    Assert.That(parse_date(inputString), Is.EqualTo(expectedMinutes));
}

У Java з testng у вас є методи
@DataProvider

це найкраще рішення ІМХО. майже будь-якою мовою ви можете параметризувати свої тести. для java: @Parameterized , JunitParams , Zohhak
piotrek

3

Так, зробіть кілька тестів для кожного варіанту введення.

Основна мета одного твердження на тест-інструкцію полягає в тому, щоб одна (в ідеалі) одна помилка призводила до одного збою тесту і навпаки, щоб ви точно знали, що не вдалося. Тоді ви можете працювати з одним дуже точним тестом, щоб налагодити першопричину і перевірити. Ви можете розірвати це одним твердженням, і ви можете гаразд з кількома твердженнями. У цьому конкретному сценарії я мав би тест на кожен суфікс і кілька комбінацій упорядкування.

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

Але історія показала, що заощаджувати мало часу на написання коду за рахунок читання / використання коду ніколи не варто. Звідси керівництво.


1

Пуристи говорять про те, що твердження про різні значення вхідних даних слід розміщувати в окремих тестових методах у межах тестового класу. Однією з причин цього є те, що, залежно від тестувального інтерфейсу, часто простіше розрізнити окремі відмови тесту, ніж між окремими твердженнями, що може призвести до того, що швидше визначити джерело відмови.

Під час тестування з JUnit ми можемо обійти це, використовуючи версію методів assrt * з початковим аргументом String, щоб диференціювати одне твердження від іншого в межах того ж методу тестування.

self.assertEqual("just minutes", parse_date('5m'), 5)
self.assertEqual("just hours", parse_date('5h'), 300)
self.assertEqual("just days", ('5d') ,7200)
self.assertEqual("days, hours, minutes", parse_date('1d4h20m'), 1700)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.