2013-12-16 12 views
32

Когда мне нужно отлаживать.заселенные кодовые контракты или наоборот? Я хочу проверить предварительное условие для метода, и я смущен, чтобы выбрать один над другим. У меня есть модульные тесты, где я хочу протестировать сценарии отказа и ожидать исключения.Debug.Assert vs Code Контракт

Полезно ли использовать протокол Debug.Assert и Code на том же методе. Если да, то каков будет порядок, в котором должен быть написан код?

Debug.Assert(parameter!= null); 
Contract.Requires<ArgumentNullException>(parameter != null, "parameter"); 

или

Contract.Requires<ArgumentNullException>(parameter != null, "parameter"); 
Debug.Assert(parameter!= null); 

Есть ли смысл всего этого?

ответ

28

Это разные вещи. Утверждение отладки выполняется только тогда, когда код компилируется как отладка и поэтому будет проверять/утверждать только при отладке. Идея состоит в том, чтобы использовать это для «проверок здравомыслия» для кода, который вы разрабатываете. Кодовые контракты могут использоваться как для отладки, так и для выпуска. Они уверяют, что предварительные и последующие условия методов соответствуют ожиданиям метода (соответствуют контракту). Существует также структура тестирования, которая обеспечивает аналогичную функциональность, предназначенную для проверки соответствия теста.

Используйте Debug.Assert, если вы хотите, чтобы определенные вещи были такими, какие вы ожидаете при разработке кода (и в дальнейшем развитии обслуживания).

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

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

+0

Я полностью согласен, но если я захочу использовать debug.assert и код контракта на том же месте, если он будет в определенном порядке? – CarbineCoder

+0

Не знаете, почему вы сделали бы двойную проверку таким образом. Порядок не должен соответствовать. Если бы я делал это, я считаю, что сначала поставил Debug.Assert в качестве средства отладки разработки. – Dweeberly

+0

Debug.Assert не будет там в коде Release, но контракты с кодом будут. Поэтому я чувствую, что есть случаи, когда debug.assert будет необходим параллельно с кодовыми контрактами - я могу ошибаться. Отсюда вопрос. – CarbineCoder

22

Лично я бы не использовать оба Debug.Assert и код контракты для обеспечения предварительных условий во вновь создаваемом коде - Контракты ИМО заменяют Debug.Assert, так как они предлагают более полный набор проверок, не говоря уже о выгоде, которую можно получить из статическая проверка, которая может быть выполнена , прежде чем код получит время работы. Сохранение дублирующих предварительных проверок как в Debug.Assert, так и в Contracts будет громоздким.

Обоснование:

  • Вам не нужно повторно коду любых устаревших предпосылок вы можете закодированные в Debug.Assert или throw кода - вы можете сохранить существующий контрольный код предусловия и terminate it with Contract.EndContractBlock()
  • You может получить одинаковое неконтролируемое поведение режима выпуска, когда System.Diagnostics.Debug построен без /d:DEBUG, если вы построите с проверкой времени выполнения контракта, установленным на None. Ref 6.2.1 in the Docs
  • Контракты позволяют разработчику быть более выразительным в коде, так как «почему» обнаружено недопустимое состояние - например, было ли это напрямую из-за внеполосного параметра (Contract.Requires). В противном случае Contract.Assert или Contract.Assume может проверить общее состояние, а «гарантированная правильность» состояния при выходе из метода может быть выражена с помощью Contract.Ensures. И Invariants выражают, что государство должно храниться постоянно.
  • И, самое главное, статическая проверка может привести к исполнению этих Контрактов при создании вашего кода. Таким образом, у вас есть шанс подобрать ошибку через время разработки или время компиляции, вместо того, чтобы ждать времени выполнения.Контрактные проверки могут быть добавлены в вашу непрерывную интеграцию для поиска несоблюдения.

Одно предостережение: если вы собираетесь писать модульные тесты, которые преднамеренно нарушают контракты, возможно, придется иметь дело с ContractException - Джон Скит объясняет это хорошо here. например Подключите Contract.ContractFailed handler в тестовой настройке к обработчику, который вызывает SetHandled, а затем выдает публичное исключение, которое вы можете поймать и утвердить в своих UT.

+2

Хорошее объяснение. Теперь я понимаю. Если использовать последовательно, это приносит столько ясности, что разработчик предполагает о состоянии приложения на всем протяжении пути. И это просто глазурь на торте, торт - это более подробные и полные процедуры обработки исключений, которые легко установить с самого начала. – jeremcc

+0

Только в том случае, если в настройке конфигурации для решения было установлено, что 'Contract.Assert' не заканчивается в сборке Release, я бы использовал их. В противном случае я использую 'Debug.Assert', потому что знаю, что они никогда не просочится в сборку Release. Конфигурационное сопровождение кодовых контрактов является самым большим недостатком ИМО. – orad

+0

Добавляя к моему предыдущему комментарию, для предварительных условий и пост-условий на публичных интерфейсах, я понимаю, почему мы хотели бы включить их в режим выпуска для использования потребительского кода. Но я не вижу причин, по которым мы хотели бы включить утверждения в режиме выпуска в любом случае. Об этом я недостаточно осведомлен. – orad