Чи дотримується одне твердження за тест нерозумної послідовності в цьому випадку?


10

У мене є клас, який я тестую. Клас має функцію:apply(List<IRule> rules, List<ITarget> targets);

В одному тесті я хочу переконатися, що кожна ціль була передана одному правилу, a la:

rule1.AssertWasCalled(fnord => fnord.Test(target1));
rule1.AssertWasCalled(fnord => fnord.Test(target2));
rule1.AssertWasCalled(fnord => fnord.Test(target3));

Мені здається, що обмеження себе в одній заяві твердження було б цілком гобгобліном . Чи я правдивий у цьому припущенні, чи є якийсь інший спосіб, який би я міг стверджувати, що кожна мета була насправді протестована?


Я бачу фронди!
Росс Паттерсон

Відповіді:


15

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

Налаштування даних тричі та трьома різними методами є марним і менш читабельним, ніж альтернатива наявності декількох тверджень.

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


3
Дійсно: правило - це більше одне логічне твердження за тест одиниці. Ви можете згрупувати їх у один вищий рівень, запевняючи, що ви можете повторно використовувати їх у різних тестах.
Лоран Буро-Рой

5

Вважаю, що це правило стверджується на тестове правило, щоб ваші тести були зосереджені на одному питанні. Якщо ви тестуєте 20 речей за один тест, то важко сказати, яке ваше покриття. Ви знаєте, що це викликає проблему, коли ви не можете назвати метод тестування без слова і в ньому. Наприклад, якщо ваш метод тестування буде точніше названий як testFooIsTrueAndDbExistsAndBarIsNullAndAnExceptionDoesntOccur(), ви, ймовірно, занадто багато тестуєте в одному тесті.

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


3

Для вашого конкретного прикладу, ви можете піти з одного твердження твердження, якщо ви робите щось на кшталт:

foreach target in targets
{
     rule1.AssertWasCalled(fnord => fnord.Test(target))
}

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


Я робив це раніше. Не поганий шлях. Це легко читати, і ви можете зрозуміти природу того, що він робить.
CokoBWare

1

Я теж боровся з цим.

Пурист (в мені) наполягає на одному твердженні за тест, тому я точно знаю * , де саме підірвались речі.

І тоді я виявляю, як вирізати / вставляти багато того самого, зайвого коду настройки тесту. Після третього чи четвертого шару цього ви починаєте говорити "Ой, досить!"

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


1
Ви повинні перевірити Assume. Я щойно дізнався про це сьогодні.
Уейн Вернер

1

Якщо код налаштування для target1Іншого відрізняється від коду установки для target2, цей тип розрізання кутів, як правило, призводить до занадто довгого коду ініціалізації тесту. Це, в свою чергу, або безлад, або закінчується реконструкцією та повторним використанням. Якщо ваші тести є досить складними, щоб виправдати їх рефакторинг, ваш тест, ймовірно, перевіряє більше ніж одне.

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

Якщо target1і target2є різними реалізаціями одного і того ж інтерфейсу, слід замість цього додати модульний тест до інтерфейсу (і дозволити вашій тестовій структурі генерувати тест для кожної реалізації цього інтерфейсу).

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