Как принять TDD и гарантировать соблюдение?

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

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

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

Сталкивающийся с этой ситуацией, я вижу только два возможных решения: (1) задним числом тесты записи на существующий код, или (2) перепишите такое количество приложения, как практично при фанатичном соблюдении принципов TDD. Я чувствую (1) как в общем и целом не практичный, потому что у нас есть адский граф зависимостей в рамках проекта. Почти ни один из наших компонентов не может быть протестирован в изоляции; мы не знаем всех вариантов использования; и случаи использования, вероятно, изменятся во время нажатия тестирования из-за бизнес-требований или как реакция на непредвиденные проблемы. По этим причинам мы не можем действительно быть уверены, что наши тесты окажутся высококачественными, как только мы сделаны. Существует риск продвижения команды в ложное чувство защищенности, посредством чего тонкие ошибки закрадутся ни с кем замечающим. Учитывая мрачные перспективы относительно ROI, мне или нашему руководителю группы было бы трудно выровнять по ширине это усилие к управлению.

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

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

В дополнение к выбору правильного подхода (также (1), (2), или другой на данный момент неизвестное решение), я нуждаюсь в помощи, отвечая на следующий вопрос: Как моя команда может гарантировать, что наше усилие не потрачено впустую в конечном счете несохраняемыми тестами и/или отказом записать новые, поскольку бизнес-требования прокручиваются на? Я открыт для широкого спектра предложений здесь, включают ли они морковь или палки.

В любом случае, благодарит читать об этом нанесенном самому себе тяжелом положении.

19
задан Max A. 26 February 2010 в 13:45
поделиться

9 ответов

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

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

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

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

Судя по вашему описанию, некоторая (или вся) часть вашего текущего кода является обязательством, а не активом.Теперь подумайте, что TDD (или любая другая дисциплина) сделает, чтобы снизить стоимость этой ответственности. Вопрос о «продуктивности» неприменим, когда вы создаете пассив.

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

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

«Практически ни один из наших компонентов не может быть протестирован изолированно; мы не знаем всех вариантов использования»

Верно. Приспособить модульные тесты к существующей кодовой базе действительно сложно.

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

Неверно. Нет никакого «ложного чувства безопасности». Все знают, что испытания в лучшем случае непростые.

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

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

«Метод (2) более привлекателен»

Да. Но.

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

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

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

Что вам нужно сделать, так это разбить ваши приложения на части.

Рассмотрим, например, уровни Модель - Услуги - Представление .

У вас есть базовая модель приложения (постоянные объекты, базовые классы и т. Д.), Которая требует обширного и тщательного тестирования, заслуживающего доверия.

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

У вас есть представления / презентации, которые требуют некоторого тестирования, но не являются основной обработкой. Это просто презентация. Он будет постоянно меняться, поскольку людям нужны разные параметры, представления, отчеты, анализ, RIA, графический интерфейс, блеск и шипение.

12
ответ дан 30 November 2019 в 03:16
поделиться

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

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

8
ответ дан 30 November 2019 в 03:16
поделиться

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

Это ваша настоящая проблема.

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

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

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

Я согласен с рекомендацией CI. Добавьте метрики покрытия кода в Hudson или Cruise Control.

Само собой разумеется, что вы используете Subversion, Git или другую систему управления исходным кодом, не так ли?

Это долгий процесс, но в конце концов он того стоит.

5
ответ дан 30 November 2019 в 03:16
поделиться

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

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

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

  • пропущенные сроки
  • раздутые бюджеты
  • марши смерти
  • выгорание разработчиков
  • программное обеспечение с ошибками
  • неудовлетворенные клиенты

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

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

2
ответ дан 30 November 2019 в 03:16
поделиться

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

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

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

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

1
ответ дан 30 November 2019 в 03:16
поделиться

Boost поставляется с некоторыми рекомендациями по программированию для портативности; библиотеки тщательно рецензируются до принятия - хотя поддержка компиляторов может быть прекращена для конкретных библиотек, если нет разумного способа реализации библиотек Raison d 'itytre, и библиотека приносит концепции прорыва - например, boost:: mpl не очень хорошо работал на солнечных компиляторах в течение длительного времени.

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

-121--3941877-

Boost достаточно хорошо протестирован в различных операционных системах

Проверьте на этой странице

-121--3941876-

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

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

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

Надеюсь, это поможет.

1
ответ дан 30 November 2019 в 03:16
поделиться

Мне нужна помощь в ответе на следующий вопрос: Как моя команда может гарантировать, что наши усилия не будут потрачены впустую в долгосрочной перспективе из-за не поддерживаемых тестов и/или неспособности написать новые тесты по мере изменения бизнес-требований?

Убедитесь, что ваш процесс сборки выполняет тесты при каждой сборке и не выполняет сборку в случае сбоев.

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

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

Обновление: Я также хочу отметить, что 100% покрытие тестами - не самая лучшая цель, оно имеет убывающую отдачу, когда вы пытаетесь перейти от ~80% или ~90%. Чтобы получить эти последние несколько процентных пунктов, вам нужно начать моделировать все возможные ответвления в вашем коде. Ваша команда начнет тратить время на моделирование сценариев, которые либо не могут произойти в реальной жизни ("этот поток на самом деле не выбросит IOException, когда я его закрою, но мне нужно, чтобы эта ветвь была покрыта!"), либо не имеют реальной ценности для вашего тестирования. Я поймал кого-то из своей команды на том, что if (foo == null) throw new NullPointerException(...); в качестве первой строки метода на самом деле вызывал исключение, когда значение было null.

Гораздо лучше потратить время на тестирование кода, который действительно имеет значение, чем заниматься навязчивым стремлением сделать так, чтобы каждая последняя строчка отображалась зеленым цветом в Emma или Cobertura.

9
ответ дан 30 November 2019 в 03:16
поделиться

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

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

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

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

1
ответ дан 30 November 2019 в 03:16
поделиться

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

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

2
ответ дан 30 November 2019 в 03:16
поделиться
Другие вопросы по тегам:

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