Подтвердить что ты не робот

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

"Существует риск привести команду в ложное чувство безопасности, при котором тонкие ошибки будут ползти без каких-либо замечаний"

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

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

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

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

Да. Но.

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

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

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

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

Ответ 5

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

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

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

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

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

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

Ответ 6

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

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

Ответ 7

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

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

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

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

Ответ 8

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

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

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

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

Ответ 9

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

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

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

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