Оба утверждения и модульные тесты служат документацией для кодовой базы и средством обнаружения ошибок. Основное различие заключается в том, что утверждения функционируют как проверки работоспособности и видят реальные входные данные, тогда как модульные тесты выполняются на конкретных смоделированных входных данных и являются тестами с одним четко определенным «правильным ответом». Каковы относительные преимущества использования проверок и модульных тестов в качестве основного средства проверки правильности? Как вы думаете, на что следует обратить особое внимание?
testing
unit-testing
assertions
dsimcha
источник
источник
:-)
Ответы:
Утверждения полезны для того, чтобы рассказать вам о внутреннем состоянии программы . Например, что ваши структуры данных имеют допустимое состояние, например, что
Time
структура данных не будет содержать значение25:61:61
. Проверенные утверждениями условия:Предпосылки, которые гарантируют, что звонящий соблюдает свой контракт,
Постусловия, которые гарантируют, что вызываемый абонент сохраняет свой контракт, и
Инварианты, которые гарантируют, что структура данных всегда имеет некоторое свойство после возврата из функции. Инвариант - это условие, которое является предварительным условием и постусловием.
Модульные тесты полезны для того, чтобы рассказать вам о внешнем поведении модуля . У вас
Stack
может быть непротиворечивое состояние после вызоваpush()
метода, но если размер стека не увеличивается в три раза после его вызова три раза, то это ошибка. (Например, тривиальный случай, когда неправильнаяpush()
реализация только проверяет утверждения и выходы.)Строго говоря, основное различие между утверждениями и модульными тестами заключается в том, что модульные тесты имеют тестовые данные (значения, которые нужно запустить программе), а утверждения - нет. То есть вы можете выполнять свои модульные тесты автоматически, в то время как вы не можете сказать то же самое для утверждений. Ради этого обсуждения я предположил, что вы говорите о выполнении программы в контексте функциональных тестов высшего порядка (которые выполняют всю программу, а не управляют модулями, такими как модульные тесты). Если вы не говорите об автоматизированных функциональных тестах как о способе «увидеть реальные входные данные», тогда ясно, что ценность заключается в автоматизации, и, таким образом, выигрывают модульные тесты. Если вы говорите об этом в контексте (автоматических) функциональных тестов, то смотрите ниже.
Там может быть некоторое совпадение в том, что тестируется. Например,
Stack
постусловие может фактически утверждать, что размер стека увеличивается на единицу. Но есть пределы тому, что может быть выполнено в этом утверждении: следует ли также проверять, что верхний элемент - это то, что было только что добавлено?Для обоих целью является повышение качества. Цель модульного тестирования - найти ошибки. Для утверждений цель состоит в том, чтобы упростить отладку, наблюдая недействительные состояния программы, как только они возникают.
Обратите внимание, что ни один из методов не проверяет правильность. Фактически, если вы проводите модульное тестирование с целью проверки правильности программы, вы, скорее всего, получите неинтересный тест, который, как вы знаете, будет работать. Это психологический эффект: вы будете делать все, чтобы достичь своей цели. Если ваша цель - найти ошибки, ваша деятельность будет отражать это.
Оба важны, и имеют свои собственные цели.
[В качестве заключительного замечания об утверждениях: чтобы получить наибольшее значение, вам нужно использовать их во всех критических точках вашей программы, а не в нескольких ключевых функциях. В противном случае первоначальный источник проблемы мог бы быть замаскирован и его трудно обнаружить без нескольких часов отладки.]
источник
Говоря об утверждениях, имейте в виду, что их можно отключить одним щелчком мыши.
Пример очень плохого утверждения:
Почему это плохо? Поскольку проверка ошибок не выполняется, если это утверждение пропущено из-за того, что определено что-то вроде NDEBUG.
Модульный тест (скорее всего) будет просто segfault в коде выше. Конечно, он сделал свое дело, сказав, что что-то пошло не так, или сделал это? Насколько вероятно
malloc()
провал теста?Утверждения предназначены для целей отладки, когда программист должен подразумевать, что никакое «нормальное» событие не вызовет срабатывание утверждения.
malloc()
провал, действительно, нормальное событие, поэтому никогда не следует утверждать.Есть много других случаев, когда утверждения используются вместо адекватной обработки вещей, которые могут пойти не так. Вот почему утверждения получают плохую репутацию, и почему такие языки, как Go, не включают их.
Модульные тесты предназначены, чтобы сказать вам, когда что-то, что вы изменили, сломало что-то другое Они разработаны , чтобы спасти вас (в большинстве случаев) от прохождения каждой функции программы (однако, тестеры имеют важное значение для релизов) каждый раз , когда вы делаете сборку.
Между этими двумя понятиями нет четкой корреляции, кроме того, что оба они говорят, что что-то пошло не так. Думайте об утверждении как о точке останова в чем-то, над чем вы работаете, без использования отладчика. Думайте о модульном тесте как о чем-то, что говорит вам, если вы сломали что-то, над чем вы не работаете.
источник
Оба эти инструмента используются для улучшения общего качества системы, которую вы строите. Многое зависит от языка, который вы используете, типа приложения, которое вы создаете, и от того, где лучше всего проводить время. Не говоря уже о том, что у вас есть несколько школ мысли об этом.
Для начала, если вы используете язык без
assert
ключевого слова, вы не можете использовать утверждения (по крайней мере, не так, как мы говорим здесь). Долгое время в Java не былоassert
ключевого слова, а во многих языках до сих пор нет. Модульное тестирование становится немного более важным. В некоторых языках утверждения выполняются только при установленном флаге (снова с Java здесь). Когда защиты не всегда есть, это не очень полезная функция.Существует школа мысли, которая говорит, что если вы «утверждаете» что-то, вы могли бы также написать
if
/throw
значимый блок исключений. Этот мыслительный процесс происходит от многих утверждений, помещенных в начале метода, чтобы гарантировать, что все значения находятся в границах. Тестирование ваших предварительных условий является очень важной частью наличия ожидаемого постусловия.Модульное тестирование - это дополнительный код, который необходимо написать и поддерживать. Для многих это недостаток. Тем не менее, с учетом текущей структуры модульных тестов, вы можете генерировать большее количество условий тестирования с помощью сравнительно небольшого кода. Параметризованные тесты и «теории» будут выполнять один и тот же тест с большим количеством образцов данных, которые могут выявить некоторые трудно обнаруживаемые ошибки.
Лично я нахожу, что получаю больше пробега с модульным тестированием, чем с опрыскивающими утверждениями, но это из-за платформ, которые я разрабатываю в большинстве случаев (Java / C #). Другие языки имеют более надежную поддержку утверждений и даже «Дизайн по контракту» (см. Ниже), чтобы обеспечить еще больше гарантий. Если бы я работал с одним из этих языков, я мог бы использовать DBC больше, чем модульное тестирование.
http://en.wikipedia.org/wiki/Design_by_contract#Languages_with_native_support
источник