Используется ли YAGNI при написании тестов?

Когда я пишу код, я пишу только те функции, которые мне нужны, когда они мне нужны.

Используется ли этот подход для написания тестов?

Должен ли я писать тест заранее для каждого случая использования, о котором я могу думать, просто для того, чтобы играть в него безопасно, или я должен только писать тесты для прецедента, когда я сталкиваюсь с ним?

Ответы

Ответ 1

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

YAGNI, как я понимаю, означает, что вам не следует разрабатывать функции, которые еще не нужны. В этом смысле вам не следует писать тест, который заставляет вас разрабатывать код, который не нужен. Я подозреваю, что это не то, о чем вы просите.

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

В последнем случае я не в состоянии дать вам окончательный ответ. Вы, конечно, хотите, чтобы ваши тесты оставались сухими - не пишите тест, который просто повторяет другой тест, даже если он имеет разные данные. Кроме того, вы не можете обнаружить потенциальные проблемы с дизайном, если не используете крайние случаи своих данных. Простым примером является метод, который вычисляет сумму двух целых чисел: что произойдет, если вы передадите его maxint как оба параметра? Если у вас есть только один тест, вы можете пропустить это поведение. Очевидно, это связано с предыдущим пунктом. Только вы можете быть уверены, когда тест действительно нужен или нет.

Ответ 2

Да YAGNI абсолютно применим к написанию тестов.

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

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

Кроме того, я бы написал тесты для проверки ввода? Абсолютно. Однако я бы сделал это до точки. Скажем, у вас есть функция с тремя параметрами, которые являются int и возвращает двойной. Сколько тестов вы собираетесь писать вокруг этой функции. Я бы использовал YAGNI здесь, чтобы определить, какие тесты приведут к хорошему ROI, и которые бесполезны.

Ответ 3

Запишите тест так, как вам нужно. Тесты - это код. Написание кучи (первоначально неудачных) тестов перед перерывом красное/исправление/зеленый цикл TDD и затрудняет определение допустимых отказов по сравнению с неписаным кодом.

Ответ 4

Вы должны написать тесты для вариантов использования, которые вы собираетесь реализовать на этом этапе разработки.

Это дает следующие преимущества:

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

Ответ 5

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

Итак, нет. YAGNI не включает тесты:)

Ответ 6

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

Что делать, если конкретный пример использования тестируемого устройства, который вы игнорируете, вызывает серьезный дефект в конечном программном обеспечении? Прошло ли время, потраченное на разработку тестов, вы купили что-нибудь в этом сценарии за ложным чувством безопасности?

(Для записи это одна из проблем, с которыми я сталкиваюсь с использованием покрытия кода для измерения качества теста - это измерение, которое, если оно мало, может указывать на то, что вы недостаточно тестируете, но если высокий, не следует использовать, чтобы предположить, что вы прочные. Получите проверенные общие случаи, проверенные кромки, затем рассмотрите все ifs, ands и buts устройства и проверьте их тоже.)

Мягкое обновление

Я должен отметить, что я исхожу из другой перспективы, чем здесь. Я часто нахожу, что я пишу код в стиле библиотеки, то есть код, который будет повторно использоваться в нескольких проектах, для нескольких разных клиентов. В результате, как правило, невозможно сказать с уверенностью, что определенных вариантов использования просто не произойдет. Лучшее, что я могу сделать, это либо документ, что они не ожидаются (и, следовательно, может потребоваться обновить тесты после этого), либо - и это мои предпочтения:) - просто написать тесты. Я часто нахожу вариант № 2 более комфортным для повседневной жизни, просто потому, что у меня гораздо больше уверенности, когда я повторно использую компонент X в новом приложении Y. И уверенность, на мой взгляд, заключается в том, что автоматическое тестирование все о.

Ответ 7

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

Для применений, которые, как вы знаете, будут реализованы, тестовые случаи подвержены уменьшающейся отдаче, т.е. попытка охватить каждый возможный неясный угловой случай не является полезной целью, когда вы можете охватить все важные и критические пути с половиной работы - предполагая, конечно, что затраты на пропущение редко возникающей ошибки являются долговечными; Я бы, конечно, не согласился на что-то менее 100% кода и охват веток при написании программного обеспечения для авионики.

Ответ 8

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

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

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

Ответ 9

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

Если вы решите протестировать более инкрементно, я могу добавить к комментариям doc, что функция "проверена только для [определенных видов ввода], результаты для других входов undefined".

Ответ 10

Я часто нахожу, что пишу тесты, TDD, для случаев, когда я не ожидаю, что обычный программный поток вызовет. Подход "поддельный, пока вы не сделаете это", я начинаю, как правило, с нулевого ввода - достаточно, чтобы иметь представление о том, как должен выглядеть вызов функции, какие типы его параметров будут иметь и какой тип он будет вернуть. Чтобы быть ясным, я не просто отправлю значение null в функцию в своем тесте; Я инициализирую типизированную переменную, чтобы сохранить нулевое значение; таким образом, когда Eclipse Quick Fix создает для меня функцию, у нее уже есть правильный тип. Но это не редкость, что я не буду ожидать, что программа обычно посылает нуль функции. Итак, возможно, я пишу тест, который я с AGN. Но если я начну со значения, иногда это слишком большой кусок. Я разрабатываю API и продвигаю его реальную реализацию с самого начала. Поэтому, начав медленно и подделывать, пока я это сделаю, иногда я пишу тесты для случаев, которые я не ожидаю увидеть в производственном коде.

Ответ 11

Если вы работаете в стиле TDD или XP, вы не будете писать что-либо "заранее", как вы говорите, вы будете работать над очень точной функциональностью в любой момент, Будем писать все необходимые тесты, чтобы убедиться, что бит функциональности работает так, как вы его намереваетесь.

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