Применяется ли YAGNI также при написании тестов?
когда я пишу код, я пишу только функции, которые мне нужны, как мне они нужны.
применяется ли этот подход также к написанию тестов?
должен ли я написать тест заранее для каждого прецедента, который я могу придумать, чтобы играть в него безопасно, или я должен писать тесты только для прецедента, когда я нахожусь на нем?
11 ответов
Я думаю, что при написании метода вы должны проверить как ожидаемые, так и потенциальные пути ошибок. Это не означает, что вы должны расширять свой дизайн, чтобы охватить каждое потенциальное использование-оставьте это, когда это необходимо, но вы должны убедиться, что ваши тесты определили ожидаемое поведение перед лицом недопустимых параметров или других условий.
YAGNI, как я понимаю, означает, что вы не должны разрабатывать функции, которые еще не нужны. В этом смысле, вы не должны написать тест, который заставляет вас разрабатывать код, который не нужен. Но я подозреваю, что вы спрашиваете не об этом.
в этом контексте я бы больше беспокоился о том, следует ли писать тесты, которые охватывают неожиданное использование - например, ошибки из-за передачи null или параметров вне диапазона-или повторять тесты, которые отличаются только в отношении данных, а не функциональности. В первом случае, как я указывал выше, я бы сказал "Да". Тесты документируют ожидается поведение вашего метода перед лицом ошибок. Это важная информация для людей, которые используют свой метод.
в последнем случае, я менее способен дать вам окончательный ответ. Вы, конечно, хотите, чтобы ваши тесты оставались сухими-не пишите тест, который просто повторяет другой тест, даже если у него другие данные. Кроме того, вы не можете обнаружить потенциальные проблемы с дизайном, если не используете крайние случаи данных. Простым примером является метод, который вычисляет сумму двух целые числа: что произойдет, если вы передадите его maxint
как параметры? Если у вас есть только один тест, вы можете пропустить это поведение. Очевидно, это связано с предыдущим пунктом. Только вы можете быть уверены, когда тест действительно нужен или нет.
да YAGNI абсолютно относится к написанию тестов.
например, я, например, не пишу тесты для проверки каких-либо свойств. Я предполагаю, что свойства работают определенным образом, и пока я не приду к тому, что делает что-то отличное от нормы, у меня не будет тестов для них.
вы всегда должны учитывать правильность написания теста. Если нет явной пользы для вас в написании теста, то я бы посоветовал вам этого не делать. Однако это явно очень субъективно, так что вы можете думать не стоит кто-то другой мог подумать очень стоит усилий.
кроме того, я бы написал тесты для проверки ввода? Абсолютно. Тем не менее, я бы сделал это до точки. Скажем, у вас есть функция с 3 параметрами, которые являются ints, и она возвращает double. Сколько тестов вы собираетесь написать вокруг этой функции. Я бы использовал YAGNI здесь, чтобы определить, какие тесты собираются получить вам хороший ROI, и которые бесполезны.
написать тест, как вам это нужно. Тесты код. Написание кучки (изначально неудачных) тестов спереди нарушает красный/исправленный / зеленый цикл TDD и затрудняет идентификацию допустимых сбоев против неписаного кода.
вы должны написать тесты для вариантов использования, которые вы собираетесь реализовать на этом этапе разработки.
Это дает следующие преимущества:
- тесты помогают определить функциональность этого этапа.
- вы знаете, когда вы завершили этот этап, потому что все ваши тесты проходят.
вы должны написать тесты, которые охватывают весь код, в идеале. В противном случае Остальные тесты потеряют значение, и в конце вы будете повторно отлаживать этот фрагмент кода.
Так, нет. YAGNI не включает тесты:)
конечно, нет смысла писать тесты для случаев использования, которые вы не уверены, будут реализованы вообще - это должно быть очевидно для всех.
для случаев использования, которые вы знаете, будут реализованы, тестовые случаи подвержены уменьшающейся отдаче, т. е. попытка охватить каждый возможный неясный угловой случай не является полезной целью, когда вы можете охватить все важные и критические пути с половиной работы-предполагая, конечно, что стоимость игнорирования редко встречающейся ошибки терпимо; я бы, конечно, не согласился ни на что меньшее, чем 100% - ный код и покрытие ветвей при написании программного обеспечения для авионики.
вы, вероятно, получите некоторую дисперсию здесь, но, как правило, цель написания тестов (для меня) заключается в том, чтобы гарантировать, что весь ваш код работает так, как он должен, без побочных эффектов, предсказуемым образом и без дефектов. Поэтому, на мой взгляд, подход, который вы обсуждаете, заключающийся только в написании тестов для случаев использования, не приносит вам никакой реальной пользы и может даже причинить вред.
Что делать, если конкретный вариант использования для тестируемого устройства, который вы игнорируете, вызывает серьезный дефект в окончательное программное обеспечение? Разве время, потраченное на разработку тестов, принесло вам что-нибудь в этом сценарии, кроме ложного чувства безопасности?
(для записи это одна из проблем, которые я имею с использованием покрытия кода для "измерения" качества теста-это измерение, которое, если низкое, может дать указание на то, что вы недостаточно тестируете, но если высокое, не следует использовать, чтобы предположить, что вы тверды как камень. Проверьте общие случаи, крайние случаи, а затем рассмотрите все ifs, ands и buts и проверить их тоже.)
Мягкий Обновления
Я должен отметить, что я прихожу, возможно, с другой точки зрения, чем многие здесь. Я часто обнаруживаю, что пишу код в стиле библиотеки, то есть код, который будет повторно использоваться в нескольких проектах для нескольких разных клиентов. В результате я вообще не могу с уверенностью сказать, что определенных вариантов использования просто не будет. Лучшее, что я могу сделать, это либо документ, который они не ожидали (и, следовательно, могут требовать обновления тестов после этого), или -- и это мое предпочтение :) -- просто писать тесты. Я часто нахожу вариант №2 более пригодным для жизни на повседневной основе, просто потому, что у меня гораздо больше уверенности, когда я повторно использую компонент X в новом приложении Y. и уверенность, на мой взгляд, - это то, что автоматизированное тестирование.
вы, безусловно, должны воздержаться от написания тестовых случаев для функциональности, которую вы еще не собираетесь реализовывать. Тесты должны быть написаны только для существующих функций или функций, которые вы собираетесь ввести.
однако варианты использования не совпадают с функциональностью. Вам нужно только проверить допустимые варианты использования, которые вы определили, но будет много других вещей, которые могут произойти, и вы хотите убедиться, что эти входные данные получат разумный ответ (который вполне может быть сообщение об ошибке.)
очевидно, вы не получите все возможные варианты использования; если бы вы могли, не было бы необходимости беспокоиться о компьютерной безопасности. Вы должны получить по крайней мере более правдоподобные, и по мере возникновения проблем вы должны добавить их в варианты использования для тестирования.
Я думаю, что ответ здесь, как и во многих местах, зависит. Если контракт, который представляет функция, утверждает, что она делает X, и я вижу, что у нее есть связанные модульные тесты и т. д. Я склонен думать, что это хорошо проверенная единица и использовать ее как таковую, даже если я не использую ее точно так же в другом месте. Если этот конкретный шаблон использования непроверен,я могу получить запутанные или труднодоступные ошибки. По этой причине, я думаю, что тест должен охватывать все (или большинство) определены, задокументированы поведение подразделения.
Если вы решите тестировать более постепенно, я мог бы добавить к комментариям doc, что функция "тестируется только для [определенных видов ввода], результаты для других входов не определены".
Я часто пишу тесты, TDD, для случаев, которые я не ожидаю, что вызовет обычный поток программы. Подход "fake it' til you make it " заставляет меня начинать, как правило, с нулевого ввода - достаточно, чтобы иметь представление о том, как должен выглядеть вызов функции, какие типы будут иметь ее параметры и какой тип она вернет. Чтобы быть ясным, я не просто отправлю null функции в моем тесте; я инициализирую типизированную переменную для хранения значения null; таким образом, когда Быстрое исправление Eclipse создает функцию для меня, она уже имеет правильный тип. Но это не редкость, что я не буду ожидать, что программа обычно отправляет null в функцию. Поэтому, возможно, я пишу тест, который я AGN. Но если я начну с ценностей, иногда это слишком большой кусок. Я как разрабатываю API, так и продвигаю его реальную реализацию с самого начала. Так что, начав медленно и притворяясь, пока я не сделаю это, иногда я пишу тесты для случаев, которые я не ожидаю увидеть в производстве код.
Если вы работаете в стиле TDD или XP, вы не будете писать ничего "заранее", как вы говорите, вы будете работать над очень точным битом функциональности в любой момент, поэтому вы будете писать все необходимые тесты, чтобы убедиться, что бит функциональности работает так, как вы намереваетесь.
тестовый код похож на сам" код", вы не будете писать код заранее для каждого случая использования вашего приложения, так почему бы вам написать тестовый код заранее ?