Когда целесообразно не тестировать устройство?

Я работаю в небольшой компании в качестве сольного разработчика. На самом деле я единственный разработчик в компании. У меня есть несколько (относительно) больших проектов, которые я написал и поддерживаю регулярно, и ни у кого из них нет тестов для их поддержки. Когда я начинаю новые проекты, я часто задаюсь вопросом, следует ли мне попробовать подход TDD. Это звучит неплохо, но я честно не могу оправдать дополнительную работу.

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

Многие примеры, которые я видел в тестах, приходят к мелочам, охватывая все аспекты кода. Поскольку я единственный разработчик, и я очень близок к коду во всем проекте, гораздо эффективнее следовать шаблону write-then-hand-test. Я также считаю, что требования и функции часто меняются настолько, что поддержание тестов приведет к значительным перетаскиваниям проекта. Время, которое в противном случае можно было бы потратить на решение бизнес-потребностей.

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

Я иногда настраивал несколько тестов, чтобы убедиться, что я правильно написал алгоритм, например, подсчитал количество лет, в течение которых кто-то был в компании на основании даты найма. Но с точки зрения охвата кода я охватил около 1% моего кода.

В моей ситуации вы все равно найдете способ сделать модульное тестирование обычной практикой, или я оправдан в том, чтобы избежать этих накладных расходов?

ОБНОВЛЕНИЕ: Несколько вещей о моей ситуации, которые я забыл: мои проекты - это все веб-приложения. Чтобы охватить весь мой код, мне пришлось бы использовать автоматические тесты пользовательского интерфейса, и это область, где я до сих пор не вижу большой пользы от ручного тестирования.

127 голосов | спросил Ken Pespisa 8 PMpFri, 08 Apr 2011 19:41:27 +040041Friday 2011, 19:41:27

14 ответов


77
  

Многие примеры, которые я видел в тестах, приходят к мелочам, охватывая все аспекты кода.

Так? Вам не нужно проверять все . Просто соответствующие вещи.

  

Поскольку я единственный разработчик, и я очень близок к коду во всем проекте, гораздо эффективнее следовать шаблону write-then-hand-test.

Это на самом деле неверно. Это не более эффективно. Это просто привычка.

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

Это очень, очень эффективно.

  

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

Это тоже ложно. Тесты не являются перетаскиванием. Изменения требований - это перетаскивание.

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

Код не выполняется, пока тесты не пройдут. Это единственная универсальная правда программного обеспечения.

У вас может быть ограниченный приемочный тест «здесь он».

Или вы можете провести некоторые модульные тесты.

Или вы можете иметь оба.

Но независимо от того, что вы делаете, всегда есть тест, демонстрирующий, что программное обеспечение работает.

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

ответил S.Lott 8 PMpFri, 08 Apr 2011 20:06:30 +040006Friday 2011, 20:06:30
98

Представьте, что у вас был набор тестов, которые могли бы запускаться в глазном свете и загорались зеленым или красным светом. Представьте, что в этом наборе тестов протестировано все ! Представьте себе, что все, что вам нужно было сделать для запуска набора тестов, это ввести ^ T. Какую силу это даст вам?

Не могли бы вы внести изменения в код, не опасаясь что-то сломать? Не могли бы вы добавить новую функцию, не опасаясь сломать старую функцию? Не могли бы вы быстро очистить грязный код, не опасаясь причинить ущерб?

Да, вы могли бы все это сделать! И что будет с вашим кодом с течением времени? Это станет чище и чище, потому что не будет риска его очистки.

Предположим, что у вас была маленькая фея на плече. Каждый раз, когда вы написали строку кода, фея добавила что-то в тестовый пакет, который проверял, что эта строка кода сделала то, что она должна была делать. Поэтому каждые пару секунд вы можете нажать ^ T и увидеть, что последняя строка кода, который вы написали, работала.

Сколько отладки вы думаете, что будете делать?

Если это звучит как фантазия, вы правы. Но реальность не сильно отличается. Замените глазную линзу на несколько секунд, и фея с дисциплиной TDD, и вы ее в значительной степени получили.

Предположим, вы вернулись к системе, которую вы построили год назад, и вы забыли, как создать один из центральных объектов. Существуют тесты, которые создают этот объект каждый путь, который он может создать. Вы можете прочитать эти тесты и пробегать память. Нужно позвонить API? Существуют тесты, которые называют этот API всеми возможными способами. Эти тесты представляют собой небольшие документы , написанные на понятном вами языке. Они совершенно недвусмысленны. Они настолько формальны, что исполняются. И они не могут выйти из синхронизации с приложением!

Не стоит инвестировать? Ты меня разыгрываешь! Как может кто-то НЕ хотеть этого набора тестов? Сделайте себе одолжение и перестаньте болтать над глупостью. Научитесь хорошо делать TDD и смотрите, как быстро вы продвигаетесь, и насколько чище ваш код.

ответил Uncle Bob. 9 AMpSat, 09 Apr 2011 03:04:34 +040004Saturday 2011, 03:04:34
32

Ошибка, которую вы делаете, заключается в том, что вы видите тестирование как инвестирование времени без немедленного возвращения. Это не обязательно так.

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

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

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

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

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

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

ответил glenatron 8 PMpFri, 08 Apr 2011 19:58:54 +040058Friday 2011, 19:58:54
30

Ребята из JUnit (платформа тестов Java Unit) имеют философию, что , если она слишком проста для тестирования, не тестируйте ее . Я настоятельно рекомендую прочитать FAQ по часто задаваемым вопросам , поскольку это довольно прагматично.

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

  1. Напишите тест
  2. Посмотрите, как это происходит (докажите, что вам нужно что-то делать)
  3. Напишите только то, что необходимо для прохождения теста - не более.
  4. Посмотрите, как проходит (yay!)
  5. Рефактор (сделайте его лучше)
  6. Промыть, полоскать и повторить

Что менее очевидно в применении TDD, так это то, что он меняет способ написания кода . Заставляя себя задуматься о том, как тестировать /проверять, работает ли код, вы пишете тестируемый код. И поскольку мы говорим об модульном тестировании, это обычно означает, что ваш код становится более модульным. Для меня модульный и проверяемый код - это большой выигрыш.

Теперь вам нужно проверить такие вещи, как свойства C #? Представьте себе свойство, определенное следующим образом:

bool IsWorthTesting {get; set;}

Ответ будет «нет», это не стоит тестировать, потому что на данный момент вы тестируете функцию языка. Просто верьте, что ребята из платформы C # поняли это правильно. Кроме того, если это не удалось, что может сделать, чтобы исправить это?

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

  • Проверенные исключения, которые могут возникнуть только в случае плохой установки. В Java их много. Вы должны написать блок catch или объявить исключенное исключение, даже если он не может выйти из строя, не взломав установленные файлы.
  • Пользовательские интерфейсы. Поиск контрольного теста и вызов правильных событий для имитации действий пользователя очень сложны, а в некоторых случаях невозможны. Однако, если вы используете шаблон Model /View /Controller, вы можете проверить, что ваша модель и контроллеры протестированы, и оставить часть обзора ручным тестированием.
  • взаимодействия клиент /сервер. Это уже не единичный тест, а теперь тест интеграции . Напишите все части, которые идут на отправку и получение сообщений по проводу, но на самом деле не переходят через провод. Хороший подход состоит в том, чтобы уменьшить ответственность за код, который фактически ведет переговоры по проводке с необработанными сообщениями. В вашем модульном тестовом коде выведите из строя объект связи, чтобы убедиться, что службы ведут себя так, как вы ожидаете.

Верьте или нет, TDD поможет вам войти в устойчивый темп развития. Это не из-за магии, а из-за того, что у вас плотный цикл обратной связи, и вы можете быстро поймать действительно немые ошибки. Стоимость исправления этих ошибок по существу постоянна (по крайней мере, достаточно для целей планирования), потому что небольшие ошибки никогда не растут, чтобы быть большими ошибками. Сравните это с бурным характером сбрасывания кода binge /debug purge.

ответил Berin Loritsch 8 PMpFri, 08 Apr 2011 20:44:16 +040044Friday 2011, 20:44:16
23

Вы должны сбалансировать стоимость тестирования со стоимостью ошибок.

Написание теста на 10 строк для функции, которая открывает файл, где ошибка «файл не найден» не имеет смысла.

Функция, которая делает что-то сложное для сложной структуры данных - тогда, очевидно, да.

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

ответил Martin Beckett 8 PMpFri, 08 Apr 2011 19:54:08 +040054Friday 2011, 19:54:08
22

Тестирование - это азартные игры.

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

Как и любая ставка, иногда вы выигрываете, иногда теряете.

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

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

ответил hotpaw2 26 PMpTue, 26 Apr 2011 23:30:12 +040030Tuesday 2011, 23:30:12
10

Мой совет - только проверить код, который вы хотите работать правильно.

Не проверяйте код, который вы хотите ошибочно, и создавайте проблемы для вас по дороге.

ответил Nick Hodges 9 AMpSat, 09 Apr 2011 09:45:55 +040045Saturday 2011, 09:45:55
8
  

Я часто задаюсь вопросом, следует ли мне попробовать подход TDD. Это звучит неплохо, но я честно не могу оправдать дополнительную работу.

TDD и Unit Testing - это не одно и то же.

Вы можете написать код, затем добавить модульные тесты позже. Это не TDD и много дополнительной работы.

TDD - это практика кодирования в цикле Red Light. Зеленый свет. Итерации рефакторинга.

Это означает, что нужно писать тесты для кода, который еще не существует, наблюдая, как тесты терпят неудачу, исправление кода, чтобы сделать тесты, а затем сделать код «правильным». Это часто спасает вас.

Одним из преимуществ TDD является то, что он уменьшает необходимость думать о мелочах. Такие вещи, как ошибки «один за другим», исчезают. Вам не нужно идти на охоту через документацию API, чтобы узнать, будет ли список, который он возвращает, начинается с 0 или 1, просто сделайте это.

ответил Paul Butcher 8 PMpFri, 08 Apr 2011 20:08:46 +040008Friday 2011, 20:08:46
3

Я работал над системой, где мы тестировали почти все. Заметным исполнением для тестирования были выходной код PDF и XLS.

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

Если результат будет субъективным, мало единицы тестирования вы можете сделать то, что стоит усилий.

ответил sal 9 AMpSat, 09 Apr 2011 00:39:20 +040039Saturday 2011, 00:39:20
2

Для многих вещей «write-then-manual-test» занимает больше времени, чем писать пару тестов. Экономия времени связана с возможностью повторного запуска этих тестов в любое время.

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

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

TL; DR Это действительно никогда , потому что преимущества слишком хороши.

ответил Steven Evers 8 PMpFri, 08 Apr 2011 19:52:43 +040052Friday 2011, 19:52:43
2

Два очень хороших ответа, которые я встретил здесь:

  1. Когда нужно выполнить тестирование unit-test vs вручную
  2. >
  3. Что не следует проверять, когда дело доходит до Unit Тестирование?

Обоснования для избежания предполагаемых издержек:

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

Не хотите ли вы оставить отличный продукт с вашей стороны в качестве доказательства качества вашей работы? Говоря в эгоистичных терминах, разве вам не лучше, что вы делаете?

ответил Aditya P 8 PMpFri, 08 Apr 2011 19:53:13 +040053Friday 2011, 19:53:13
1

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

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

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

Я бы не вернулся и написал целую партию тестов для кода, который вы уже отправили, но в следующий раз вам нужно будет изменить функцию, которую я предлагаю попробовать написать тесты для этого модуля или класса, получить свой охват до 70% + перед внесением любых изменений. Смотрите, помогает ли это вам.

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

ответил Steve Haigh 8 PMpFri, 08 Apr 2011 20:00:13 +040000Friday 2011, 20:00:13
1

Похоже, что большинство ответов являются про-TDD, хотя вопрос не спрашивал о TDD, а об модульных тестах вообще.

Не существует абсолютно объективного правила, лежащего в основе того, что тестировать на модуле или нет. Но есть пара раз, когда кажется, что многие программисты не тестируют единицу:

  1. Частные методы

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

  1. Вещи, которые вы уже знаете, должны работать (или вещи, проверенные кем-то другим).

Многие новые программисты идут вразрез с этим, когда они впервые учатся тестировать, и считают, что им нужно протестировать каждую выполняемую линию. Если вы используете внешнюю библиотеку, и ее функциональность хорошо протестирована и документирована ее авторами, обычно нет смысла тестировать специфические функциональные возможности модульных тестов. Например, кто-то может написать тест, чтобы убедиться, что их модель ActiveRecord сохраняет правильное значение для атрибута с обратным вызовом «before_save» в базе данных, хотя это поведение само по себе уже тщательно протестирован в Rails. Метод (ы), который вызывает обратный вызов, возможно, но не поведение самого обратного вызова. Любые основные проблемы с импортированными библиотеками лучше выявить с помощью приемочных тестов, а не модульных тестов.

Оба из них могут применить, выполняете ли вы TDD или нет.

ответил Ravenstine 5 MaramSat, 05 Mar 2016 01:53:38 +03002016-03-05T01:53:38+03:0001 2016, 01:53:38
0

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

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

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

public interface ITest {
    public string Name {
        get;
    }
    public string Description {
        get;
    }
    public List<ITest> SubTests {
        get;
    }
    public TestResult Execute();
}

public class TestResult {
    public bool Succesful {
        get;
        set;
    }

    public string ResultMessage {
        get;
        set;
    }

    private Dictionary<ITest, TestResult> subTestResults = new Dictionary<ITest, TestResult>();
    public Dictionary<ITest, TestResult> SubTestResults {
        get {
            return subTestResults;
        }
        set {
            subTestResults = value;
        }
    }
}

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

Построение адресной книги будет требовать меньше тестирования, чем поисковая система предприятия, но основы не меняются.

Удачи!

ответил Adam Carstensen 8 PMpFri, 08 Apr 2011 20:53:36 +040053Friday 2011, 20:53:36

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132