Как принять TDD и обеспечить соблюдение? - PullRequest
19 голосов
/ 26 февраля 2010

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

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

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

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

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

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

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

В любом случае, спасибо, что прочитали об этом самоубийстве.

Ответы [ 9 ]

12 голосов
/ 26 февраля 2010

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

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

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

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

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

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

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

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

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

«Существует риск привести команду к ложному чувству безопасности, из-за которого незаметно появятся тонкие ошибки, и никто не заметит»

Ложь. Там нет "ложного чувства безопасности". Все знают, что тестирование в лучшем случае непросто.

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

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

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

Да. Но.

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

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

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

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

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

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

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

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

9 голосов
/ 26 февраля 2010

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

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

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

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

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

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

8 голосов
/ 26 февраля 2010

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

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

5 голосов
/ 26 февраля 2010

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

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

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

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

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

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

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

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

2 голосов
/ 26 февраля 2010

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

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

2 голосов
/ 26 февраля 2010

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

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

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

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

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

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

1 голос
/ 02 марта 2010

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

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

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

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

1 голос
/ 26 февраля 2010

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

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

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

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

1 голос
/ 26 февраля 2010

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

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

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

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

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