Полезно ли использовать методы юнит-тестирования, где единственная логика - это охрана

12

Скажем, у меня есть такой метод:

public void OrderNewWidget(Widget widget)
{
   if ((widget.PartNumber > 0) && (widget.PartAvailable))
   {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

У меня есть несколько таких методов в моем коде (передняя часть асинхронного вызова веб-службы).

Я спорю, полезно ли их покрывать юнит-тестами. Да, здесь есть логика, но это только охранная логика. (Это означает, что я должен убедиться, что у меня есть то, что мне нужно, прежде чем разрешить вызов веб-службы.)

Часть меня говорит: «Конечно, вы можете тестировать их, но это не стоит времени» (я работаю над проектом, который уже отстает от графика).

Но другая сторона меня говорит, что если вы не тестируете их модулем, а кто-то меняет Страж, тогда могут быть проблемы.

Но первая часть меня говорит обратно: если кто-то меняет охрану, то вы просто делаете для них больше работы (потому что теперь им нужно сменить охранников и юнит-тесты для охранников).

Например, если моя служба берет на себя ответственность за проверку доступности виджета, то я, возможно, больше не хочу этого охранника. Если он находится на модульном тесте, мне нужно поменять два места сейчас.

Я вижу плюсы и минусы в обоих направлениях. Поэтому я решил спросить, что сделали другие.

Vaccano
источник
17
Вы не делаете «больше работы» для сопровождающих. Если они меняют логику, они должны изменить соответствующие юнит-тесты. Вот как это работает. Я не вижу твоих минусов: если твой модульный тест не требует изменения, то это не будет ничего проверять, не так ли? Вы также можете спросить, полезен ли юнит-тестирование вообще.
Андрес Ф.
9
Это не по теме, но я бы изменил логику, чтобы выбрасывать исключение, если номер детали равен 0 или меньше, или если деталь недоступна, так как, на мой взгляд, было бы ошибкой разрешить кому-либо вызывать этот метод с фиктивный виджет, молча маскирующий еще одну проблему.
Мэтью
2
@ Матфея очень хорошая мысль. Эта функция лежит. Название говорит вам, что он что-то закажет. И тогда это не так, но вы никогда не узнаете, если вы не примените ту же логику, что и внутри, что означает СУХОЕ. Другими словами: если бы дизайн был изменен, чтобы быть более правильным, этот вопрос, возможно, не был бы задан в первую очередь.
Стийн
2
but it is not worth the time" (I am on a project that is already behind schedule).Мы разработчики программного обеспечения. Единственный раз, когда мы находимся на графике, это когда мы мертвы :)
maple_shaft

Ответы:

26

Часть меня говорит: «Конечно, вы можете тестировать их, но это не стоит времени» (я работаю над проектом, который уже отстает от графика).

Это три очень коротких теста. Вы потратили столько времени, чтобы задать себе вопрос.

Но другая сторона меня говорит, что если вы не тестируете их модулем, а кто-то меняет Страж, тогда могут быть проблемы.

Послушай эту сторону.

Но первая часть меня говорит обратно: если кто-то меняет охрану, то вы просто делаете для них больше работы (потому что теперь им нужно сменить охранников и юнит-тесты для охранников).

Если ваш сопровождающий - болтун TDD, вы усложняете им задачу. Любые изменения, которые я делаю, без каких-либо изменений или добавлений тестов, заставляют меня задуматься. На самом деле, я бы, вероятно, добавил тесты, прежде чем идти дальше и вносить изменения.

Первая часть вас просто неправильно. Дайте второй части похлопать по спине и перестаньте думать об этом.

прецизионный самописец
источник
+1 за краткость, хотя я тоже написал ответ, хе
Джимми Хоффа
3
+1. Да, если требования изменятся, некоторые тесты должны быть адаптированы.
Оливье Жако-Дескомб
Хотя мне нравится то, что вы говорите, в моем коде есть много случаев такого вызова (передняя половина асинхронного вызова). Так что это не просто 3 модульных теста. Тем не менее, если это «правильный» путь, то я хочу сделать их.
Vaccano
@Vaccano: Чем больше из них вы должны написать, тем больше логических путей у вас нет тестов и тем более необходимо их написать.
фунтовые
9

Это упростило бы модульное тестирование, если бы логика защиты и фактическое упорядочение были отдельными методами.

В Widgetклассе

public bool IsReadyForOrdering { get { return PartNumber > 0 && PartAvailable; } }

или эквивалентный метод где-то еще

public bool IsWidgetReadyForOrdering(Widget widget)
{
    return widget.PartNumber > 0 && widget.PartAvailable;
}

Метод заказа

public void OrderNewWidget(Widget widget)
{
   if (IsWidgetReadyForOrdering(widget)) {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Теперь тестирование IsWidgetReadyForOrderingстало легким. Не думай больше об этом. Проверь это!

Оливье Жако-Дескомб
источник
1
Ох, логика с состоянием в свойстве .. -1, это должен быть метод, и он должен принимать PartNumber, PartAvailable из-за своей простоты. Сделайте его защищенным, если он не должен быть частью общедоступного API, а не свойством. Также я обычно не согласен. Защитная логика внутри метода полностью в порядке, и, на мой взгляд, лучше, потому что это такой маленький метод, что вы просто загрязняете класс, чтобы уменьшить и без того маленький метод. Добавьте его к классу в этом случае, только если это повторяющаяся логика.
Джимми Хоффа
1
Во-первых, это не отвечает на вопрос. Во-вторых, это неправда. Вам нужно написать три теста в любом случае. В-третьих, он раскрывает детали реализации вызывающему коду без необходимости.
фунтовые
8
@JimmyHoffa: где вы видите логику с состоянием в этом свойстве? Фактически, в примере показано, как отделить логику изменения состояния (OrderNewWidget) от логики без изменения состояния (ReadyForOrdering). И я твердо верю, что извлечение даже этих небольших функций улучшит код, а не ухудшит его, как вы заявляете. Так что +1.
Док Браун
2
Этот метод OrderNewWidget, вероятно, находится в другом классе, чем Widget, поскольку он имеет Widgetаргумент. Поскольку метод не имеет возвращаемого значения, тестирование не является очевидным. Вы должны будете ввести WigdetOrderingService-mock, который отслеживает OrderNewWidgetAsyncвызов.
Оливье Жако-Дескомб
2
@JimmyHoffa: на самом деле, ваше определение «без состояния» означает «статический» в C #. Таким образом, вы говорите, что «свойства не должны иметь доступ к состоянию объекта». Но даже тупые получатели обращаются к переменным состояния, так что это будет означать «писать только статические свойства» - что, кажется, не имеет особого смысла.
Док Браун
6

Если у вас нет времени в вашем расписании для модульного тестирования, но у вас есть время отложить на твердое использование QA, спросите, можете ли вы украсть часть этого времени для написания модульных тестов или можете потратить часть периода QA проводить модульные тесты, или, возможно, просто иметь дело с не тестируемым модулем кодом. К сожалению, графики, которые являются неподвижными, вынуждают вас идти на уступки или работать самостоятельно до смерти, я обычно предлагаю первый вариант, потому что второй приведет к тому, что вы не сможете поддерживать / поддержание системы в течение срока ее действия.

Тем не менее, на ваш общий вопрос о проверке охранных заявлений; Да! Абсолютно проверить охранные высказывания! Это важные части поведения этого метода, вы бы не хотели, чтобы кто-то неправильно понял, что-то делает исправление ошибки, снял вашу охрану или поменял ее &&на другую, ||не так ли? Модульные тесты гарантируют, что: а) вы действительно правильно поняли логику своих охранников и б) никто не нарушит эту логику позже, не получив жалоб, когда они запустят юнит-тесты, говорящие им, что так должно быть по какой-то причине.

Джимми Хоффа
источник
0

Выше приведены отличные ответы, и они очень важны. Но то, что, кажется, было упущено, это то, что у вас есть полный набор модульных тестов, они читаются как чрезвычайно детальная спецификация кода. Если вы пропустите проверку тестирования только потому, что код настолько прост, что трудно понять, как он может пойти не так, часть вашей спецификации отсутствует. Если бы я попал в команду, где эти тесты были пропущены, я бы предположил, что ваша служба не проверяет свои аргументы.

Жюль
источник
-5

Код есть код. Вы должны попытаться получить 100% покрытие при тестировании. Если бы это не было важно, его бы там не было.

суперпользователя
источник