Я действительно влюбился в модульное тестирование и TDD - я заражен тестом.
Тем не менее, модульное тестирование обычно используется для общедоступных методов. Хотя иногда мне приходится проверять некоторые предположения-утверждения и в частных методах, потому что некоторые из них «опасны», и рефакторинг не может помочь в дальнейшем. (Я знаю, что инфраструктуры тестирования позволяют тестировать частные методы).
Так что стало моей привычкой, что первая и последняя строка частного метода являются утверждениями.
Тем не менее, я заметил, что я склонен использовать утверждения в публичных методах (а также в приватных) просто «для уверенности». Может ли это быть «проверкой дублирования», поскольку предположения общедоступного метода проверяются извне структурой модульного тестирования?
Может ли кто-то думать о слишком многих утверждениях как о запахе кода?
источник
Ответы:
Эти утверждения действительно полезны для проверки ваших предположений, но они также служат другой действительно важной цели: документации. Любой читатель открытого метода может прочитать утверждения, чтобы быстро определить предварительные и последующие условия, не обращая внимания на набор тестов. По этой причине я рекомендую хранить эти утверждения по причинам, связанным с документацией, а не по причинам тестирования. Технически вы дублируете утверждения, но они служат двум различным целям и очень полезны в обоих случаях.
Хранить их как утверждения лучше, чем просто использовать комментарии, потому что они активно проверяют предположения при каждом запуске.
источник
Похоже, вы пытаетесь сделать дизайн-по-контракту вручную.
Делать DbC - хорошая идея, но вы должны, по крайней мере, рассмотреть вопрос о переходе на язык, который поддерживает его изначально (например, Eiffel ), или, по крайней мере, использовать систему контрактов для вашей платформы (например, Microsoft Code Contracts для .NET).это довольно красиво, возможно, самая сложная структура контракта, даже более мощная, чем Eiffel). Таким образом, вы можете лучше использовать силу контрактов. Например, используя существующую платформу, вы можете отобразить контракты в своей документации или IDE (например, контракты кода для .NET показаны в IntelliSense и, если у вас VS Ultimate, даже могут статически проверяться автоматическим средством проверки теорем во время компиляции, пока вы печатаете, также во многих Java-контрактных средах есть доклеты JavaDoc, которые автоматически извлекают контракты в вашу документацию по JavaDoc API).
И даже если окажется, что в вашей ситуации нет альтернативы делать это вручную, вы теперь, по крайней мере, знаете, как это называется, и можете прочитать об этом.
Итак, вкратце: если вы действительно делаете DbC, даже если вы этого не знаете, тогда эти утверждения совершенно хороши.
источник
Всякий раз, когда у вас нет полного контроля над вашими входными параметрами, это очень хорошая идея, чтобы заранее проверить на наличие простых ошибок. Сбой на ноль, например.
Это не дублирование ваших тестов, так как они должны проверить, что код не работает должным образом, учитывая неверные входные параметры, а затем задокументировать это .
Я не думаю, что вы должны утверждать возвращаемые параметры (если у вас явно нет инварианта, который вы хотите, чтобы читатель понял). Это также работа юниттестов.
Лично мне не нравится
assert
утверждение в Java, так как они могут быть отключены, и тогда это ложная защита.источник
Я думаю, что использование утверждений в публичных методах еще более важно, так как там вы не контролируете входные данные и, скорее всего, будет нарушено предположение.
Проверка входных условий должна выполняться всеми открытыми и защищенными методами. Если входные данные передаются напрямую в закрытый метод, то проверка его входных данных может быть избыточной.
Тестирование выходных условий (например, состояния объекта или этого возвращаемого значения! = Null) должно выполняться во внутренних методах (например, в закрытых методах). Если выходные данные передаются напрямую из закрытого метода в выходные данные открытого метода без дополнительных вычислений или изменений внутреннего состояния, то тестирование условий вывода открытого метода может быть излишним.
Однако я согласен с Олекси в том, что избыточность может повысить удобочитаемость, а также может повысить удобство сопровождения (если прямое назначение или возврат больше не будет иметь место в будущем).
источник
Трудно быть не зависящим от языка в этом вопросе, поскольку детали того, как реализуются утверждения и «правильная» обработка ошибок / исключений, имеют отношение к ответу. Вот мои 0,02 доллара, основанные на моих знаниях Java и C ++.
Утверждения в частных методах - это хорошо, если вы не идете за борт и не размещаете их повсюду . Если вы помещаете их в действительно простые методы или неоднократно проверяете такие вещи, как неизменяемые поля, то вы напрасно загромождаете код.
Утверждения в публичных методах обычно лучше избегать. Вы все равно должны делать такие вещи, как проверка того, что контракт метода не нарушен, но если это так, то вы должны генерировать исключения с подходящей типизацией со значимыми сообщениями, возвращать состояние, где это возможно, и т. Д. (Что @rwong называет «полным правильная обработка ошибок ").
Вообще говоря, вы должны использовать только утверждения, чтобы помочь вашей разработке / отладке. Вы не можете предполагать, что у тех, кто использует ваш API, даже при включении вашего кода будут включены утверждения. Хотя они действительно помогают в документировании кода, часто есть лучшие способы документировать одни и те же вещи (например, документация по методам, исключения).
источник
Добавление к списку (в основном) исключительных ответов, еще одна причина большого количества утверждений и дублирования в том, что вы не знаете, как, когда или кем класс будет изменен в течение срока его службы. Если вы пишете выбрасываемый код, который будет мертв через год, не беспокойтесь. Если вы пишете код, который будет использоваться через 20 с лишним лет, он будет выглядеть совсем по-другому - и сделанное вами предположение может оказаться недействительным. Парень, который делает это изменение, поблагодарит вас за утверждения.
Также не все программисты идеальны - опять же, утверждения означают, что один из этих «промахов» не будет распространяться слишком далеко.
Не стоит недооценивать влияние этих утверждений (и других проверок на допущения) на снижение стоимости обслуживания.
источник
Наличие дублирующих утверждений само по себе не является неправильным, но утверждение «просто чтобы убедиться» не является лучшим. Это действительно сводится к тому, что именно каждый тест пытается выполнить. Только отстаивайте то, что абсолютно необходимо. Если тест использует Moq для проверки того, что метод вызван, на самом деле не имеет значения, что происходит после того, как этот метод вызван, тест касается только того, чтобы метод был вызван.
Если каждый отдельный модульный тест имеет один и тот же набор утверждений, за исключением одного или двух, то при небольшом рефакторинге все тесты могут завершиться неудачей по одной и той же причине, вместо того, чтобы показать истинное влияние рефакторинга. Вы можете оказаться в ситуации, когда вы запустите все тесты, все они не пройдены, потому что каждый тест имеет одинаковые утверждения, вы исправляете этот сбой, снова запускаете тесты, они проваливаются по другой причине, вы исправляете этот сбой. Повторите, пока не сделано.
Также рассмотрите обслуживание вашего тестового проекта. Что происходит, когда вы добавляете новый параметр или выходные данные слегка подправляются, придется ли вам возвращаться обратно через кучу тестов и изменять утверждение или добавлять утверждение? И, в зависимости от вашего кода, вам может понадобиться гораздо больше настроек, чтобы убедиться, что все утверждения пройдены.
Я могу понять привлекательность желания включить дубликаты утверждений в модульный тест, но это действительно излишне. Я пошел по тому же пути с моим первым тестовым проектом. Я ушел от этого, потому что одно только обслуживание сводило меня с ума.
источник
Если ваша инфраструктура тестирования допускает средства доступа, тогда неплохо бы использовать модульное тестирование частных методов (IMO).
Я делаю. Утверждения в порядке, но ваша первая цель должна состоять в том, чтобы сценарий был даже невозможен ; не только то, что этого не происходит.
источник
Это плохая практика.
Вы не должны тестировать публичные / приватные методы. Вы должны проверить класс в целом. Просто убедитесь, что у вас есть хорошее освещение.
Если вы пойдете (примитивный) способ тестирования каждого метода в отдельности, как правило, вам будет очень сложно реорганизовать свой класс в будущем. И это одна из лучших вещей, которые TDD позволяет вам делать.
Кроме того, это дублирование. Кроме того, это говорит о том, что автор кода действительно не знал, что он делал. И самое смешное, что вы делаете .
Некоторые люди относятся к своим тестам с меньшей осторожностью, чем их производственный код. Они не должны. Во всяком случае, мой опыт предлагает даже относиться к тестам с большей осторожностью. Они того стоят.
источник