Jump to content

Разработка через тестирование

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

Альтернативный подход к написанию автоматических тестов — написать весь рабочий код перед началом тестового кода или написать весь тестовый код перед началом рабочего кода. В TDD оба пишутся вместе.

, основанной на тестировании, TDD связано с концепцией экстремального программирования которая началась в 1999 году. [1] но в последнее время вызвал более общий интерес сам по себе. [2]

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

История [ править ]

Инженер-программист Кент Бек , которому приписывают разработку или «заново открытие» [4] В 2003 году было заявлено, что TDD поощряет простые конструкции и внушает доверие. [5]

Первоначальное описание TDD было в древней книге по программированию. В нем говорилось, что вы берете входную ленту, вручную вводите ожидаемую выходную ленту, а затем программируете до тех пор, пока фактическая выходная лента не будет соответствовать ожидаемому результату. После того, как я написал первую платформу xUnit на Smalltalk, я вспомнил, что прочитал это, и опробовал ее. Для меня это было источником TDD. Описывая TDD программистам старшего возраста, я часто слышу: «Конечно. А как еще можно программировать?» Поэтому я называю свою роль «зановым открытием» TDD.

Кент Бек , Почему Кент Бек говорит о «повторном открытии» разработки через тестирование? Какова история разработки через тестирование до повторного открытия Кента Бека?, Кент Бек (11 мая 2012 г.). «Почему Кент Бек говорит о «повторном открытии» разработки через тестирование?» . Проверено 1 декабря 2014 г.

Цикл кодирования [ править ]

Графическое представление жизненного цикла разработки через тестирование.

Шаги TDD несколько различаются в зависимости от автора по количеству и описанию, но обычно они следующие. Они основаны на книге «Разработка через тестирование на примере» . [5] Кента Бека и статья о Canon TDD .

1. Перечислите сценарии использования новой функции.
Перечислите ожидаемые варианты нового поведения. «Есть базовый случай, а затем что, если время ожидания этой службы истечет, и что, если ключа еще нет в базе данных и…» Разработчик может узнать эти спецификации, задав вопросы о вариантах использования и историях пользователей . Ключевое преимущество TDD заключается в том, что он заставляет разработчика сосредоточиться на требованиях перед написанием кода. Это контрастирует с обычной практикой, когда модульные тесты пишутся только после кода.
2. Напишите тест для пункта из списка.
Напишите автоматический тест, который пройдет , если будет соблюден вариант нового поведения.
3. Запустите все тесты. Новый тест должен провалиться – по ожидаемым причинам
Это показывает, что для желаемой функции действительно необходим новый код. Он подтверждает тестового оборудования правильность работы . Это исключает возможность того, что новый тест ошибочен и всегда пройдет успешно.
4. Напишите простейший код, который пройдет новый тест
Неэлегантный код и жесткое кодирование приемлемы. Код будет доработан на шаге 6. Никакой код, выходящий за пределы тестируемой функциональности, добавлять нельзя.
5. Теперь все тесты должны пройти.
Если какой-либо из тестов не пройден, исправьте неудачные тесты с минимальными изменениями, пока все не пройдут.
6. При необходимости выполните рефакторинг, гарантируя, что все тесты продолжают проходить.
Код подвергается рефакторингу для удобства чтения и сопровождения. В частности, из производственного кода следует удалить жестко запрограммированные тестовые данные. Запуск набора тестов после каждого рефакторинга гарантирует, что ни одна существующая функциональность не будет нарушена. Примеры рефакторинга:
Повторить
Повторяйте процесс, начиная с шага 2, для каждого теста в списке, пока все тесты не будут реализованы и пройдены.

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

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

Работа через тестирование [ править ]

TDD был принят за пределами разработки программного обеспечения как в продуктовых, так и в сервисных группах, как работа, основанная на тестировании . [6] Чтобы тестирование было успешным, его необходимо практиковать на микро- и макроуровнях. Каждый метод в классе, каждое значение входных данных, сообщение журнала и код ошибки, а также другие точки данных, должны быть протестированы. [7] Подобно TDD, команды, не связанные с программным обеспечением, перед началом работы разрабатывают проверки контроля качества (QC) (обычно ручные, а не автоматические тесты) для каждого аспекта работы. Эти проверки качества затем используются для информирования о дизайне и подтверждения соответствующих результатов. Шесть шагов последовательности TDD применяются с небольшими семантическими изменениями:

  1. «Добавить проверку» заменяет «Добавить тест»
  2. «Выполнить все проверки» заменяет «Выполнить все тесты».
  3. «Сделать работу» заменяет «Написать код».
  4. «Выполнить все проверки» заменяет «Выполнить тесты».
  5. «Навести порядок» заменяет «Рефакторинг кода».
  6. "Повторить"

Стиль разработки [ править ]

Существуют различные аспекты использования разработки через тестирование, например, принципы «будьте проще, глупее» ( KISS ) и « вам это не понадобится » (YAGNI). Сосредоточив внимание на написании только кода, необходимого для прохождения тестов, проекты часто могут быть более чистыми и понятными, чем это достигается другими методами. [5] В книге «Разработка через тестирование на примере » Кент Бек также предлагает принцип « Притворяйся, пока не сделаешь ».

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

Сначала напишите тесты. Тесты следует писать до начала тестирования функциональности. Утверждается, что это имеет множество преимуществ. Это помогает гарантировать, что приложение написано с учетом возможности тестирования, поскольку разработчики должны продумать, как тестировать приложение с самого начала, а не добавлять его позже. Это также гарантирует, что будут написаны тесты для каждой функции. Кроме того, написание тестов в первую очередь приводит к более глубокому и раннему пониманию требований к продукту, обеспечивает эффективность тестового кода и позволяет постоянно уделять внимание качеству программного обеспечения . [8] При написании кода, ориентированного на функцию, разработчики и организации склонны подталкивать разработчика к следующей функции, даже полностью игнорируя тестирование. Первый тест TDD может сначала даже не скомпилироваться, поскольку требуемые для него классы и методы могут еще не существовать. Тем не менее, этот первый тест служит началом спецификации исполняемого файла. [9]

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

Видимость кода [ править ]

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

В объектно-ориентированном проектировании это по-прежнему не обеспечивает доступ к частным данным и методам. Поэтому для модульных тестов может потребоваться дополнительная работа. В Java и других языках разработчик может использовать отражение для доступа к частным полям и методам. [10] В качестве альтернативы можно использовать внутренний класс для хранения модульных тестов, чтобы они могли видеть члены и атрибуты включающего класса. В .NET Framework и некоторых других языках программирования частичные классы могут использоваться для предоставления частных методов и данных для доступа тестов.

Важно, чтобы такие хаки тестирования не оставались в рабочем коде. В C и других языках директивы компилятора , такие как #if DEBUG ... #endif могут быть размещены вокруг таких дополнительных классов и всего остального кода, связанного с тестированием, чтобы предотвратить их компиляцию в выпущенный код. Это означает, что выпущенный код не совсем совпадает с тем, что было протестировано. Регулярное выполнение меньшего количества, но более полных, сквозных интеграционных тестов в финальной сборке релиза может гарантировать (помимо прочего), что не существует производственного кода, который тонко полагается на аспекты тестового оборудования.

Среди практиков TDD ведутся споры, документированные в их блогах и других публикациях, относительно того, разумно ли вообще тестировать частные методы и данные. Некоторые утверждают, что частные члены — это всего лишь деталь реализации, которая может измениться, и что это должно быть разрешено без нарушения количества тестов. Таким образом, должно быть достаточно протестировать любой класс через его открытый интерфейс или через интерфейс его подкласса, который в некоторых языках называется «защищенным» интерфейсом. [11] Другие говорят, что важнейшие аспекты функциональности могут быть реализованы в частных методах, и их непосредственное тестирование дает преимущество более мелких и прямых модульных тестов. [12] [13]

Фейки, макеты и интеграционные тесты [ править ]

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

Когда разрабатываемый код опирается на базу данных, веб-службу или любой другой внешний процесс или службу, принудительное разделение на модульное тестирование также является возможностью и движущей силой для разработки более модульного, более тестируемого и многократно используемого кода. [14] Необходимо два шага:

  1. Всякий раз, когда в окончательном проекте требуется внешний доступ, следует определить интерфейс , описывающий доступный доступ. См. принцип инверсии зависимостей для обсуждения преимуществ этого независимо от TDD.
  2. Интерфейс должен быть реализован двумя способами, один из которых действительно обращается к внешнему процессу, а другой является поддельным или макетным . Поддельным объектам нужно сделать немного больше, чем добавить сообщение, например «Объект Person сохранен», в журнал трассировки тестовое утверждение , для которого можно запустить для проверки правильного поведения. Мок-объекты отличаются тем, что сами содержат тестовые утверждения , которые могут привести к сбою теста, например, если имя человека и другие данные не соответствуют ожиданиям.

Методы фальшивых и ложных объектов, которые возвращают данные якобы из хранилища данных или пользователя, могут помочь процессу тестирования, всегда возвращая одни и те же реалистичные данные, на которые могут положиться тесты. Их также можно перевести в заранее определенные режимы отказа, чтобы можно было разработать и надежно протестировать процедуры обработки ошибок. В режиме ошибки метод может вернуть недопустимый, неполный или нулевой ответ или может выдать исключение . Поддельные службы, отличные от хранилищ данных, также могут быть полезны в TDD: поддельная служба шифрования может фактически не шифровать передаваемые данные; поддельная служба случайных чисел всегда может возвращать 1. Поддельные или макетные реализации являются примерами внедрения зависимостей .

Тестовый дубль — это специфичная для теста возможность, которая заменяет системную возможность, обычно класс или функцию, от которой зависит проверяемое оборудование. Двойники тестов могут быть введены в систему в двух случаях: ссылка и выполнение. Подмена времени ссылки — это когда тестовый дубль компилируется в загрузочный модуль, который выполняется для проверки тестирования. Этот подход обычно используется при работе в среде, отличной от целевой среды, которая требует дублирования кода аппаратного уровня для компиляции. Альтернативой замене компоновщика является замена во время выполнения, при которой реальная функциональность заменяется во время выполнения тестового примера. Эта замена обычно выполняется путем переназначения известных указателей функций или замены объекта.

Тестовые дубли бывают разных типов и различной сложности:

  • Манекен . Манекен — это простейшая форма тестового двойника. Это облегчает замену времени компоновщика, предоставляя при необходимости возвращаемое значение по умолчанию.
  • Заглушка . Заглушка добавляет к манекену упрощенную логику, обеспечивая различные выходные данные.
  • Шпион. Шпион фиксирует и предоставляет доступ к параметрам и информации о состоянии, публикуя средства доступа для проверки кода на наличие частной информации, что позволяет выполнять более сложную проверку состояния.
  • Mock — макет определяется отдельным тестовым примером для проверки поведения конкретного теста, проверки значений параметров и последовательности вызовов.
  • Симулятор. Симулятор представляет собой комплексный компонент, обеспечивающий более точное приближение к целевым возможностям (то, что удваивается). Симулятор обычно требует значительных дополнительных усилий по разработке. [8]

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

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

  • The TearDown метод, который является неотъемлемой частью многих платформ тестирования.
  • try...catch...finally Структуры обработки исключений, если они доступны.
  • Транзакции базы данных , где транзакция атомарно включает в себя, возможно, операции записи, чтения и соответствующего удаления.
  • Создание «снимка» базы данных перед запуском каких-либо тестов и возврат к снимку после каждого запуска теста. Это можно автоматизировать с помощью такой платформы, как Ant или NAnt , или системы непрерывной интеграции, такой как CruiseControl .
  • Инициализация базы данных до чистого состояния перед тестами, а не очистка после них. Это может быть актуально в тех случаях, когда очистка может затруднить диагностику сбоев тестирования из-за удаления конечного состояния базы данных до того, как можно будет выполнить детальную диагностику.

Держите устройство небольшим [ править ]

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

  • Сокращение усилий по отладке. При обнаружении сбоев тестирования использование меньших модулей помогает отслеживать ошибки.
  • Самодокументируемые тесты. Небольшие тестовые примеры легче читать и понимать. [8]

Передовые методы разработки через тестирование могут привести к разработке через приемочное тестирование (ATDD) и спецификации на примере , где критерии, указанные заказчиком, автоматизируются в приемочные тесты, которые затем запускают традиционный процесс разработки через модульное тестирование (UTDD). [15] Этот процесс гарантирует, что у клиента будет автоматизированный механизм принятия решения о том, соответствует ли программное обеспечение его требованиям. Благодаря ATDD перед командой разработчиков теперь стоит конкретная цель — приемочные тесты, — что позволяет им постоянно концентрироваться на том, чего клиент действительно хочет от каждой пользовательской истории.

Лучшие практики [ править ]

Структура теста [ править ]

Эффективная компоновка тестового примера гарантирует выполнение всех необходимых действий, улучшает читаемость тестового примера и упрощает поток выполнения. Последовательная структура помогает создать самодокументируемый тестовый пример. Обычно применяемая структура тестовых примеров включает (1) настройку, (2) выполнение, (3) проверку и (4) очистку.

  • Настройка. Приведите тестируемый модуль (UUT) или всю тестовую систему в состояние, необходимое для проведения теста.
  • Выполнение: запуск/управление проверяемым оборудованием для выполнения целевого поведения и захвата всех выходных данных, таких как возвращаемые значения и выходные параметры. Этот шаг обычно очень прост.
  • Валидация: убедитесь, что результаты теста верны. Эти результаты могут включать явные выходные данные, полученные во время выполнения, или изменения состояния проверяемого оборудования.
  • Очистка: восстановление проверяемого оборудования или всей тестовой системы до состояния, предшествующего тестированию. Это восстановление позволяет выполнить другой тест сразу после этого. В некоторых случаях, чтобы сохранить информацию для возможного анализа сбоев теста, очистку следует начинать непосредственно перед запуском установки теста. [8]

Индивидуальные лучшие практики [ править ]

Некоторые передовые методы, которым может следовать человек, заключаются в том, чтобы разделить общую логику настройки и демонтажа на службы поддержки тестирования, используемые соответствующими тестовыми примерами, чтобы каждый тестовый оракул был сосредоточен только на результатах, необходимых для проверки его теста, и разрабатывать тесты, связанные со временем, чтобы обеспечить устойчивость к выполнению в операционных системах, не работающих в режиме реального времени. Обычная практика, предусматривающая запас в 5–10 процентов на позднее выполнение, снижает потенциальное количество ложноотрицательных результатов при выполнении теста. Также предлагается относиться к тестовому коду с тем же уважением, что и к рабочему коду. Тестовый код должен корректно работать как в положительных, так и в отрицательных случаях, работать долго, быть читабельным и удобным в сопровождении. Команды могут собраться вместе и просмотреть тесты и методы тестирования, чтобы поделиться эффективными методами и избавиться от вредных привычек. [16]

Практики, которых следует избегать, или «анти-паттерны» [ править ]

  • Наличие тестовых примеров зависит от состояния системы, манипулируемого ранее выполненными тестовыми примерами (т. е. вы всегда должны запускать модульный тест из известного и предварительно настроенного состояния).
  • Зависимости между тест-кейсами. Набор тестов, в котором тестовые примеры зависят друг от друга, является хрупким и сложным. Порядок исполнения не должен предполагаться. Базовый рефакторинг первоначальных тестовых примеров или структуры проверяемого оборудования вызывает спираль все более распространенных воздействий на связанные тесты.
  • Взаимозависимые тесты. Взаимозависимые тесты могут вызывать каскад ложноотрицательных результатов. Сбой в первом тестовом примере нарушает последующий тестовый пример, даже если в проверяемом оборудовании нет фактической неисправности, что увеличивает усилия по анализу дефектов и отладке.
  • Тестирование точного исполнения, поведения, времени или производительности.
  • Создание «всезнающих оракулов». Оракул, который проверяет больше, чем необходимо, со временем становится более дорогим и хрупким. Эта очень распространенная ошибка опасна, поскольку она приводит к незаметному, но повсеместному снижению времени во всем сложном проекте. [16] [ нужны разъяснения ]
  • Детали реализации тестирования.
  • Медленное выполнение тестов.

Сравнение и разграничение [ править ]

TDD и ATDD [ править ]

Разработка через тестирование связана с разработкой через приемочное тестирование (ATDD), но отличается от нее. [17] TDD — это прежде всего инструмент разработчика, помогающий создать хорошо написанную единицу кода (функцию, класс или модуль), которая правильно выполняет набор операций. ATDD — это инструмент связи между заказчиком, разработчиком и тестировщиком, позволяющий гарантировать четкое определение требований. TDD требует автоматизации тестирования. ATDD этого не делает, хотя автоматизация помогает при регрессионном тестировании. Тесты, используемые в TDD, часто могут быть получены из тестов ATDD, поскольку модули кода реализуют некоторую часть требований. Тесты ATDD должны быть доступны для чтения заказчиком. TDD-тесты не нужны.

TDD и BDD [ править ]

BDD ( разработка, основанная на поведении ) сочетает в себе практики TDD и ATDD. [18] Он включает в себя сначала практику написания тестов, но фокусируется на тестах, описывающих поведение, а не на тестах, проверяющих единицу реализации. Такие инструменты, как JBehave , Cucumber , Mspec и Specflow, предоставляют синтаксисы, которые позволяют владельцам продуктов, разработчикам и инженерам по тестированию совместно определять поведение, которое затем можно преобразовать в автоматизированные тесты.

Программное обеспечение для TDD [ править ]

Существует множество фреймворков и инструментов тестирования, полезных в TDD.

Фреймворки xUnit [ править ]

компьютерного Разработчики могут использовать среды тестирования , обычно называемые xUnit (которые являются производными от SUnit, созданного в 1998 году), для создания и автоматического запуска тестовых примеров. Платформы xUnit предоставляют возможности проверки тестов в стиле утверждений и отчеты о результатах. Эти возможности имеют решающее значение для автоматизации, поскольку они переносят бремя проверки выполнения с независимой постобработки на операцию, которая включена в выполнение теста. Платформа выполнения, предоставляемая этими средами тестирования, позволяет автоматически выполнять все тестовые сценарии системы или различные их подмножества, а также другие функции. [19]

Результаты TAP [ править ]

Платформы тестирования могут принимать выходные данные модульного теста в независимом от языка протоколе Test Anything, созданном в 1987 году.

TDD для сложных систем [ править ]

Для реализации TDD в больших и сложных системах требуется модульная архитектура, четко определенные компоненты с опубликованными интерфейсами и упорядоченное многоуровневое распределение систем с максимальной независимостью от платформы. Эти проверенные методы обеспечивают повышенную тестируемость и облегчают применение автоматизации сборки и тестирования. [8]

для тестируемости Проектирование

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

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

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

Управление тестами для больших команд [ править ]

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

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

разработки через тестирование Преимущества и недостатки

Преимущества [ править ]

Разработка через тестирование (TDD) — это подход к разработке программного обеспечения, при котором тесты пишутся до фактического кода. Он предлагает несколько преимуществ:

  1. Комплексное тестовое покрытие : TDD гарантирует, что весь новый код будет пройден хотя бы одним тестом, что приводит к созданию более надежного программного обеспечения.
  2. Повышенная уверенность в коде . Разработчики получают большую уверенность в надежности и функциональности кода.
  3. Хорошо документированный код . В результате этого процесса естественным образом создается хорошо документированный код, поскольку каждый тест проясняет назначение тестируемого кода.
  4. Ясность требований : TDD способствует четкому пониманию требований до начала кодирования.
  5. Облегчает непрерывную интеграцию : он хорошо интегрируется с процессами непрерывной интеграции, позволяя часто обновлять код и тестировать.
  6. Повышает производительность . Многие разработчики считают, что TDD повышает их производительность.
  7. Укрепляет ментальную модель кода : TDD помогает создать надежную ментальную модель структуры и поведения кода.
  8. Акцент на дизайне и функциональности : поощряет акцент на дизайне, интерфейсе и общей функциональности программы.
  9. Уменьшает потребность в отладке . Выявляя проблемы на ранних этапах процесса разработки, TDD снижает необходимость в дальнейшей отладке.
  10. Стабильность системы . Приложения, разработанные с использованием TDD, как правило, более стабильны и менее подвержены ошибкам. [20]

Недостатки [ править ]

Однако TDD не лишен недостатков:

  1. Увеличение объема кода . Реализация TDD может привести к увеличению базы кода, поскольку тесты увеличивают общий объем написанного кода.
  2. Ложная безопасность от тестов . Большое количество пройденных тестов иногда может дать обманчивое ощущение безопасности относительно надежности кода.
  3. Накладные расходы на обслуживание . Поддержание большого набора тестов может увеличить накладные расходы на процесс разработки.
  4. Отнимающие много времени процессы тестирования . Написание и поддержка тестов может занять много времени.
  5. Настройка среды тестирования : TDD требует настройки и поддержания подходящей среды тестирования.
  6. Кривая обучения : Чтобы овладеть практиками TDD, требуются время и усилия.
  7. Чрезмерное усложнение . Чрезмерное внимание к TDD может привести к тому, что код окажется более сложным, чем необходимо.
  8. Пренебрежение общим дизайном . Слишком узкое внимание к прохождению тестов иногда может привести к пренебрежению более широкой картиной проектирования программного обеспечения.
  9. Увеличение затрат . Дополнительное время и ресурсы, необходимые для TDD, могут привести к увеличению затрат на разработку.

Преимущества [ править ]

Исследование 2005 года показало, что использование TDD означает написание большего количества тестов, и, в свою очередь, программисты, написавшие больше тестов, как правило, работают более продуктивно. [21] Гипотезы, касающиеся качества кода и более прямой корреляции между TDD и производительностью, оказались безрезультатными. [22]

Программисты, использующие чистый TDD в новых (« с нуля ») проектах, сообщали, что они лишь изредка ощущали необходимость вызывать отладчик . При использовании в сочетании с системой контроля версий в случае неожиданного сбоя тестов возврат кода к последней версии, прошедшей все тесты, часто может быть более продуктивным, чем отладка. [23]

Разработка через тестирование предлагает больше, чем просто проверку правильности, но также может способствовать разработке программы. [24] Сосредоточившись в первую очередь на тестовых примерах, необходимо представить, как функциональность используется клиентами (в первом случае — тестовые примеры). Итак, программист занимается интерфейсом до реализации. Это преимущество дополняет проектирование по контракту , поскольку оно подходит к коду через тестовые примеры, а не через математические утверждения или предубеждения.

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

Хотя это правда, что с TDD требуется больше кода, чем без TDD, из-за кода модульного теста, общее время реализации кода может быть короче, согласно модели Мюллера и Падберга. [25] Большое количество тестов помогает ограничить количество дефектов в коде. Ранний и частый характер тестирования помогает выявить дефекты на ранних этапах цикла разработки, не позволяя им стать эндемичными и дорогостоящими проблемами. Устранение дефектов на ранних стадиях процесса обычно позволяет избежать длительной и утомительной отладки на более поздних стадиях проекта.

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

Поскольку для прохождения неудачного тестового примера не пишется больше кода, чем необходимо, автоматические тесты, как правило, охватывают каждый путь кода. Например, разработчик TDD может добавить else перейти к существующему if заявлении, разработчику сначала придется написать неудачный тестовый пример, который мотивирует ветку. В результате автоматические тесты, полученные с помощью TDD, обычно бывают очень тщательными: они обнаруживают любые неожиданные изменения в поведении кода. Это обнаруживает проблемы, которые могут возникнуть, когда изменение на более позднем этапе цикла разработки неожиданно изменяет другие функции.

Мадейски [26] предоставил эмпирические доказательства (посредством серии лабораторных экспериментов с более чем 200 разработчиками) превосходства практики TDD над традиционным подходом Test-Last или подходом тестирования на корректность в отношении более низкой связи между объектами (CBO). Средний размер эффекта представляет собой средний (но близкий к большому) эффект на основе метаанализа проведенных экспериментов, что является важным выводом. Это предполагает лучшую модульность (т.е. более модульную конструкцию), более легкое повторное использование и тестирование разработанных программных продуктов благодаря практике программирования TDD. [26] Мадейски также измерил влияние практики TDD на модульные тесты, используя покрытие ветвей (BC) и индикатор оценки мутаций (MSI). [27] [28] [29] которые являются показателями тщательности и эффективности обнаружения ошибок модульных тестов соответственно. Влияние TDD на покрытие филиалов было средним и поэтому считается существенным. [26] Эти результаты впоследствии были подтверждены дальнейшими, меньшими экспериментальными оценками TDD. [30] [31] [32] [33]

для Психологические преимущества программиста

  1. Повышенная уверенность : TDD позволяет программистам с уверенностью вносить изменения или добавлять новые функции. Знание того, что код постоянно тестируется, снижает страх нарушить существующую функциональность. Эта система безопасности может стимулировать более инновационные и творческие подходы к решению проблем.
  2. Уменьшение страха перед изменениями, снижение стресса . При традиционной разработке изменение существующего кода может быть сложной задачей из-за риска появления ошибок. TDD с его обширным набором тестов уменьшает этот страх, поскольку тесты немедленно выявляют любые проблемы, вызванные изменениями. Знание того, что кодовая база имеет защитную сеть тестов, может снизить стресс и беспокойство, связанные с программированием. Разработчики могут чувствовать себя более расслабленными и открытыми для экспериментов и рефакторинга.
  3. Улучшенная направленность : написание тестов сначала помогает программистам сконцентрироваться на требованиях и дизайне, прежде чем писать код. Такой фокус может привести к более четкому и целенаправленному кодированию, поскольку разработчик всегда осознает цель, которую он пытается достичь.
  4. Чувство достижения и удовлетворенность работой . Прохождение тестов может обеспечить быстрое и регулярное чувство выполненного долга, повышая моральный дух. Это может быть особенно мотивирующим в долгосрочных проектах, где конечная цель может показаться далекой. Сочетание всех этих факторов может привести к повышению удовлетворенности работой. Когда разработчики чувствуют себя уверенно, сосредоточенно и являются частью сплоченной команды, их общая удовлетворенность работой может значительно повыситься.

Ограничения [ править ]

Разработка через тестирование не обеспечивает достаточного тестирования в ситуациях, когда для определения успеха или неудачи требуются полные функциональные тесты, из-за широкого использования модульных тестов. [34] Примерами являются пользовательские интерфейсы , программы, работающие с базами данных , а также некоторые программы, зависящие от конкретных сети конфигураций . TDD призывает разработчиков помещать в такие модули минимальное количество кода и максимизировать логику, содержащуюся в тестируемом библиотечном коде, используя подделки и макеты для представления внешнего мира. [35]

Поддержка руководства очень важна. Если вся организация не поверит, что разработка через тестирование улучшит продукт, руководство может почувствовать, что время, потраченное на написание тестов, потрачено зря. [36]

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

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

Тесты становятся частью накладных расходов на сопровождение проекта. Плохо написанные тесты, например те, которые включают жестко закодированные строки ошибок, сами по себе склонны к сбоям, и их дорого поддерживать. Особенно это касается хрупких тестов . [37] Существует риск того, что тесты, регулярно генерирующие ложные сбои, будут игнорироваться, так что при возникновении реального сбоя его можно будет не обнаружить. Можно писать тесты, требующие минимального и простого обслуживания, например, путем повторного использования строк ошибок, и это должно быть целью на этапе рефакторинга кода , описанном выше.

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

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

Конференция [ править ]

Первая конференция TDD прошла в июле 2021 года. [38] Конференции записывались на YouTube [39]

См. также [ править ]

Ссылки [ править ]

  1. ^ Ли Коупленд (декабрь 2001 г.). «Экстремальное программирование» . Компьютерный мир. Архивировано из оригинала 5 июня 2011 года . Проверено 11 января 2011 г.
  2. Перейти обратно: Перейти обратно: а б Ньюкирк Дж.В. и Воронцов А.А. Разработка через тестирование в Microsoft .NET , Microsoft Press, 2004.
  3. ^ Фезерс, М. Эффективная работа с устаревшим кодом, Прентис Холл, 2004 г.
  4. ^ Кент Бек (11 мая 2012 г.). «Почему Кент Бек говорит о «повторном открытии» разработки через тестирование?» . Проверено 1 декабря 2014 г.
  5. Перейти обратно: Перейти обратно: а б с Бек, Кент (8 ноября 2002 г.). Разработка через тестирование на примере . Васим: Эддисон Уэсли. ISBN  978-0-321-14653-3 .
  6. ^ Лейборн, Э. (2013) Управление гибкой организацией: бережливый подход к управлению бизнесом . Лондон: Издательство IT Governance: 176–179.
  7. ^ Мохан, Гаятри. «Полное тестирование» . www. ThoughtWorks.com . Проверено 7 сентября 2022 г.
  8. Перейти обратно: Перейти обратно: а б с д и ж г «Информационный документ по эффективному TDD для сложных встраиваемых систем» (PDF) . Решения Pathfinder. Архивировано из оригинала (PDF) 16 марта 2016 г.
  9. ^ «Гибкая разработка через тестирование» . Проворный шерпа. 3 августа 2010 г. Архивировано из оригинала 23 июля 2012 г. Проверено 14 августа 2012 г.
  10. ^ Бертон, Росс (12 ноября 2003 г.). «Подрыв защиты доступа Java для модульного тестирования» . О'Рейли Медиа, Инк . Проверено 12 августа 2009 г.
  11. ^ ван Россум, Гвидо; Варшава, Барри (5 июля 2001 г.). «PEP 8 — Руководство по стилю для кода Python» . Фонд программного обеспечения Python . Проверено 6 мая 2012 г.
  12. ^ Ньюкирк, Джеймс (7 июня 2004 г.). «Тестирование частных методов/переменных-членов — стоит или не следует» . Корпорация Майкрософт . Проверено 12 августа 2009 г.
  13. ^ Столл, Тим (1 марта 2005 г.). «Как тестировать частные и защищенные методы в .NET» . КодПроект . Проверено 12 августа 2009 г.
  14. ^ Фаулер, Мартин (1999). Рефакторинг — улучшение дизайна существующего кода . Addison Wesley Longman, Inc. Бостон: ISBN  0-201-48567-2 .
  15. ^ Коскела, Л. «Test Driven: TDD и Acceptance TDD для разработчиков Java», Manning Publications, 2007
  16. Перейти обратно: Перейти обратно: а б Разработка через тестирование (TDD) для внедрения сложных систем на YouTube от Pathfinder Solutions
  17. ^ Lean-Agile-разработка на основе приемочных испытаний: лучшее программное обеспечение благодаря сотрудничеству . Бостон: Эддисон Уэсли Профессионал. 2011. ISBN  978-0321714084 .
  18. ^ «БДД» . Архивировано из оригинала 8 мая 2015 г. Проверено 28 апреля 2015 г.
  19. ^ «Эффективное TDD для сложных встраиваемых систем» . Решения Pathfinder. Архивировано из оригинала 20 августа 2013 г. Проверено 27 ноября 2012 г.
  20. ^ Преимущества и недостатки разработки через тестирование - LASOFT
  21. ^ Эрдогмус, Хакан; Морисио, Торчиано. «Об эффективности подхода к программированию, основанного на тестировании» . Труды IEEE Transactions по разработке программного обеспечения, 31 (1). Январь 2005 г. (NRC 47445). Архивировано из оригинала 22 декабря 2014 г. Проверено 14 января 2008 г. Мы обнаружили, что учащиеся, которые сначала тестировали, в среднем писали больше тестов, и, в свою очередь, учащиеся, которые писали больше тестов, имели тенденцию быть более продуктивными.
  22. ^ Проффитт, Джейкоб. «TDD доказал свою эффективность! Или нет?» . Архивировано из оригинала 6 февраля 2008 г. Проверено 21 февраля 2008 г. Таким образом, отношение TDD к качеству в лучшем случае проблематично. Его связь с производительностью более интересна. Я надеюсь, что будет проведено дальнейшее исследование, потому что цифры производительности просто не очень хорошо для меня складываются. Существует неоспоримая корреляция между производительностью и количеством тестов, но эта корреляция на самом деле сильнее в группе без TDD (в которой было одно отклонение по сравнению с примерно половиной группы TDD, находящейся за пределами диапазона 95%).
  23. ^ Ллопис, Ноэль (20 февраля 2005 г.). «Шагая в Зазеркалье: Разработка игр через тестирование (Часть 1)» . Игры изнутри . Проверено 1 ноября 2007 г. Сравнивая [TDD] с подходом к разработке, не основанным на тестировании, вы заменяете все мысленные проверки и пошаговые действия отладчика кодом, который проверяет, что ваша программа делает именно то, что вы задумали.
  24. ^ Майр, Хервиг (2005). Разработка инженерного программного обеспечения в проектных группах (2-е, новое изд.). Мюнхен: Fachbuchverl. Лейпциг в Карл-Ханзер-Верль. п. 239. ИСБН  978-3446400702 .
  25. ^ Мюллер, Маттиас М.; Падберг, Фрэнк. «О возврате инвестиций в разработку через тестирование» (PDF) . Университет Карлсруэ, Германия. п. 6. S2CID   13905442 . Архивировано из оригинала (PDF) 8 ноября 2017 г. Проверено 14 июня 2012 г.
  26. Перейти обратно: Перейти обратно: а б с Мадейски, Л. «Разработка через тестирование — эмпирическая оценка гибкой практики», Springer, 2010 г., ISBN   978-3-642-04287-4 , стр. 1-245. DOI: 978-3-642-04288-1.
  27. ^ Влияние программирования Test-First на охват ветвей и показатель мутационной оценки модульных тестов: эксперимент. Л. Мадейски, Информационные и программные технологии, 52(2): 169-184 (2010).
  28. ^ О влиянии парного программирования на тщательность и эффективность поиска ошибок модульных тестов, Л. Мадейски PROFES 2007: 207-221
  29. ^ Влияние парного программирования на тщательность и эффективность обнаружения ошибок в наборах модульных тестов. Л. Мадейски Программный процесс: совершенствование и практика 13 (3): 281-295 (2008).
  30. ^ М. Панчур и М. Цигларич, «Влияние разработки через тестирование на производительность, код и тесты: контролируемый эксперимент», Информационные и программные технологии, 2011, том. 53, нет. 6, стр. 557–573, DOI: 10.1016/j.infsof.2011.02.002.
  31. ^ Д. Фуччи, Х. Эрдогмус, Б. Турхан, М. Ойво и Н. Юристо, «Анализ процесса разработки через тестирование: действительно ли важно тестировать первым или тестировать последним?», IEEE Труды по программной инженерии, 2017, вып. 43, нет. Т. 7, стр. 597–614, DOI: 10.1109/TSE.2016.2616877.
  32. ^ А. Тосун, О. Диесте Тубио, Д. Фуччи, С. Вегас, Б. Турхан, Х. Эрдогмус, А. Сантос, М. Ойво, К. Торо, Дж. Ярвинен и Н. Юристо, «Индустрия эксперимент по влиянию разработки через тестирование на внешнее качество и производительность», Empirical Software Engineering, 2016, том. 22, стр. 1–43, DOI: 10.1007/s10664-016-9490-0.
  33. ^ Б. Папис, К. Гроховски, К. Субзда и К. Сийко, «Экспериментальная оценка разработки через тестирование с участием стажеров, работающих над реальным промышленным проектом», IEEE Transactions on Software Engineering, 2020, DOI: 10.1109/TSE.2020.3027522
  34. ^ «Проблемы с TDD» . Dalkescientific.com. 29 декабря 2009 г. Проверено 25 марта 2014 г.
  35. ^ Хантер, Эндрю (19 октября 2012 г.). «Злоупотребляют ли модульными тестами?» . Simple-talk.com . Проверено 25 марта 2014 г.
  36. ^ Логран, Стив (6 ноября 2006 г.). «Тестирование» (PDF) . Лаборатории HP . Проверено 12 августа 2009 г.
  37. ^ «Хрупкие испытания» .
  38. ^ Бунарджич, Алекс. «Первая международная конференция по разработке через тестирование (TDD)» . Конференция ТДД . Проверено 20 июля 2021 г.
  39. ^ Первая международная конференция TDD — суббота, 10 июля 2021 г. , заархивировано из оригинала 21 декабря 2021 г. , получено 20 июля 2021 г.

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: ca25bb184b2a4fd62a906870b184d741__1716523500
URL1:https://arc.ask3.ru/arc/aa/ca/41/ca25bb184b2a4fd62a906870b184d741.html
Заголовок, (Title) документа по адресу, URL1:
Test-driven development - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)