У меня есть класс, который я тестирую. У класса есть функция:apply(List<IRule> rules, List<ITarget> targets);
В одном тесте я хочу убедиться, что каждая цель была передана одному правилу, а именно:
rule1.AssertWasCalled(fnord => fnord.Test(target1));
rule1.AssertWasCalled(fnord => fnord.Test(target2));
rule1.AssertWasCalled(fnord => fnord.Test(target3));
Мне кажется, что ограничиться одним утверждением было бы просто хобгоблином . Я прав в этом предположении, или есть какой-то другой способ, которым я мог бы утверждать, что каждая цель, на самом деле, была проверена?
unit-testing
code-quality
Уэйн Вернер
источник
источник
Ответы:
Три утверждения по сути являются одним тестом. Вы тестируете поведение метода в коллекции, чтобы убедиться, что каждый элемент был параметром для определенного вызова (т. Е. Что каждый элемент был обработан должным образом).
Установка данных три раза и тремя различными способами является расточительной и менее читаемой, чем альтернатива, состоящая из нескольких утверждений.
«Правило» единственного утверждения больше относится к созданию утверждений разных типов в одних и тех же методах (по сути, для проверки разных вещей), что в действительности не применимо в этом случае, когда вы проверяете одно поведение.
источник
Я считаю, что это одно утверждение для каждого теста, чтобы ваши тесты были сосредоточены на одной проблеме. Если вы тестируете 20 вещей за один тест, очень сложно сказать, каков ваш охват. Вы знаете, что это вызывает проблему, когда вы не можете назвать метод теста без слова и в нем. Например, если ваш метод теста будет более точно назван как
testFooIsTrueAndDbExistsAndBarIsNullAndAnExceptionDoesntOccur()
, вы, вероятно, слишком много тестируете в одном тесте.В вашем случае, я думаю, что это нормально утверждать три раза. Если вы хотите сделать ваш код более читабельным, вы можете извлечь эти три утверждения в метод с именем
assertWasCalledOnTargets(...)
.источник
Для вашего конкретного примера вы можете использовать «один» оператор assert, если вы делаете что-то вроде:
Это то, что я делаю, чтобы избежать чувства вины за то, что в одном тесте было несколько утверждений.
источник
Я тоже боролся с этим.
Пурист (во мне) настаивает на одном утверждении за тест, так что я точно буду знать , где все взорвалось.
А потом я обнаружил, что копирую / вставляю много одного и того же избыточного кода для настройки теста. После третьего или четвертого слоя вы начинаете говорить "Ой! Хватит!"
Мой компромисс состоял в том, чтобы найти аспекты, которые «никогда» не ломаются. И я сложу эти кусочки вместе, а затем добавлю один новый элемент, который может сломаться. Просто для ясности, наложение нескольких изменчивых областей в одном тесте было бы нарушением этого компромисса.
источник
Assume
. Я только что узнал об этом сегодня.Если код настройки для
target1
отличается от кода настройки дляtarget2
, этот тип обрезки углов в конечном итоге приводит к чрезмерно длинному коду инициализации теста. Это, в свою очередь, либо беспорядок, либо заканчивается рефакторингом и повторным использованием. Если ваши тесты достаточно сложны, чтобы оправдать их рефакторинг, ваш тест, вероятно, проверяет более чем одну вещь.Если код настройки для каждой цели по сути одинаков, разделение теста на несколько отдельных тестов, вероятно, является излишним.
Если
target1
иtarget2
являются разными реализациями одного и того же интерфейса, вы должны вместо этого добавить модульный тест в интерфейс (и позволить вашей тестовой среде генерировать тест для каждой реализации этого интерфейса).источник