Тестовые случаи и утверждения утверждения - PullRequest
12 голосов
/ 11 сентября 2008

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

assert(value>0); //Precondition
if (value>0)
{
  //Doit
}

Я никогда не пишу оператор if. Достаточно утверждать / все, что вы можете сделать. "Сбой рано, часто сбой"

CodeComplete состояния:

  • Утверждение assert делает приложение корректным
  • If-test делает приложение Robust

Я не думаю, что вы сделали приложение более надежным, исправив неверные значения ввода или пропустив код:

assert(value >= 0 );  //Precondition
assert(value <= 90);  //Precondition
if(value < 0)         //Just in case
  value = 0;
if (value > 90)       //Just in case
  value = 90;
//Doit

Эти исправления основаны на предположениях, которые вы сделали относительно внешнего мира. Только вызывающий объект знает, что такое «допустимое входное значение» для вашей функции, и он должен проверить ее действительность, прежде чем он вызовет вашу функцию.

Перефразировать CodeComplete : «Реальные программы становятся слишком грязными, когда мы не полагаемся исключительно на утверждения».

Вопрос: не прав ли я, упрямый, глупый, слишком не оборонительный ...

Ответы [ 9 ]

10 голосов
/ 11 сентября 2008

Проблема доверия только к утверждениям заключается в том, что они могут быть отключены в производственной среде. Цитировать статью в Википедии:

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

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

4 голосов
/ 11 сентября 2008

Используйте утверждения для проверки ввода, которым вы управляете: частные методы и т. Д.

Используйте операторы if для проверки ввода, который вы не контролируете: общедоступные интерфейсы, предназначенные для потребления пользователем, тестирование ввода пользователем и т. Д.

Протестируйте ваше приложение со встроенными утверждениями. Затем разверните без утверждений.

3 голосов
/ 11 сентября 2008

В некоторых случаях утверждения отключаются при сборке для выпуска. Возможно, вы не можете контролировать это (в противном случае вы можете строить с включенными утверждениями), поэтому было бы неплохо сделать это следующим образом.

Проблема с «исправлением» входных значений заключается в том, что вызывающая сторона не получит того, что ожидает, и это может привести к проблемам или даже сбоям в совершенно разных частях программы, что делает отладку кошмаром.

Обычно я выкидываю исключение в операторе if, чтобы взять на себя роль assert в случае, если они отключены

assert(value>0);
if(value<=0) throw new ArgumentOutOfRangeException("value");
//do stuff
2 голосов
/ 11 сентября 2008

Я бы не согласился с этим утверждением:

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

Абонент может подумать , что он знает, что введенное значение является правильным. Только автор метода знает, как это работает. Лучшая цель программиста - заставить клиента попасть в « яму успеха ». Вы должны решить, какое поведение является более подходящим в данном случае. В некоторых случаях неправильные входные значения могут быть простыми, в других вы должны выбросить исключение \ возврат ошибки.

Что касается утверждений, я бы повторил другие комментарии, assert - это проверка отладки проверки времени для автора кода, а не для клиентов кода.

1 голос
/ 11 сентября 2008

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

Если, с другой стороны, вы не пишете логику для обработки всех случаев (возможно, из-за того, что нет смысла пытаться продолжить с неверным вводом), тогда я бы использовал утверждение assertion и придерживался подхода «ранний отказ» .

1 голос
/ 11 сентября 2008

Если я правильно помню из CS-класса

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

Так что я согласен. Обычно вам не нужны оба.

Как прокомментировал Рик, это может вызвать проблемы, если вы удалите утверждения в выпущенном коде. Обычно я делаю это только в критических местах.

0 голосов
/ 11 сентября 2008

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

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

Для меня это ситуация ИЛИ:

(цитата Эндрю) «Защитите от всех диапазонов неверного ввода, я бы не стал беспокоиться об утверждении в первую очередь». -> написать тест if.

(цитата aku) "неверные вводимые значения могут быть простыми" -> написать утверждение.

Я не могу стоять оба ...

0 голосов
/ 11 сентября 2008

Для внутренних функций, которые будут использоваться только вами, используйте только asserts . Утверждения помогут выявить ошибки во время тестирования, но не повлияют на производительность при работе.

Проверьте входы, которые исходят извне, с помощью if-условий . Внешне это где-то за пределами кода, который вы / ваша команда контролируете и тестируете.

При желании вы можете иметь оба . Это будет сделано для внешних функций, где интеграционное тестирование будет проводиться до производства.

0 голосов
/ 11 сентября 2008

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

...