Можно ли успешно добавить модульное тестирование в существующий производственный проект? Если так, то как и стоит ли это?

Я настоятельно рекомендую добавить модульное тестирование в существующий проект, который находится в разработке. Он был запущен 18 месяцев назад, прежде чем я действительно смог увидеть какую-либо пользу от TDD (face palm) , так что теперь это довольно большое решение с несколькими проектами, и я не представляю себе, с чего начать добавление юнит-тестов. Что заставляет меня задуматься об этом, так это то, что иногда старая ошибка, кажется, всплывает наружу, или ошибка фиксируется как исправленная без действительно исправления. Модульное тестирование уменьшит или предотвратит возникновение этих проблем.

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

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

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

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

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

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

Так что я думаю, что я тоже спрашиваю; [12265 Стоит ли усилий для существующее решение, которое находится в производстве?

  • Было бы лучше игнорировать тестирование для этого проекта и добавить его в возможное будущее переписать?
  • Что будет более полезным; расходы несколько недель, добавляя тесты или несколько недели, добавляющие функциональность?
  • (Очевидно, что ответ на третий пункт полностью зависит от того, говорите ли вы с руководством или разработчиком)


    Причина для награды

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

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

    131
    задан Community 23 May 2017 в 12:26
    поделиться

    22 ответа

    Я ввел модульные тесты для кодовых баз, в которых его раньше не было. В последнем большом проекте, в котором я участвовал, когда я пришел в команду, продукт уже находился в производстве с нулевыми юнит-тестами. Когда я ушел - 2 года спустя - у нас было около 4500 или около того тестов, дающих около 33% покрытия кода в кодовой базе с 230000 + производственным LOC (финансовое приложение Win-Forms в реальном времени). Это может показаться низким, но результатом стало значительное улучшение качества кода и количества дефектов, а также повышение морального духа и прибыльности.

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

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

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

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

    Теперь, для ваших комментариев и вопросов:

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

    Краткий ответ: Да, вы пропустите тесты, и да, они могут изначально не выглядеть так, как если бы они были в ситуации «зеленого поля».

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

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

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

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

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

    Существуют ли какие-либо процессы / шаги, которых следует придерживаться, чтобы гарантировать, что существующие решения правильно протестированы, а не просто внедрены?

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

    Обучайте своих людей.

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

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

    Сборка всегда должна быть БЫСТРОЙ. Если ваше время сборки медленное, ваши навыки модульного тестирования отстают. Найдите медленные тесты и улучшите их (разделите производственный код и тестируйте изолированно). Хорошо написано, вы легко сможете провести несколько тысяч модульных тестов и при этом завершить сборку менее чем за 10 минут (~ 1-несколько мс / тест - хороший, но очень приблизительный ориентир, некоторые исключения могут применяться, например, код с использованием отражения и т. Д. ).

    Осмотрите и адаптируйте.

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

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

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

    Два приблизительных вторичных показателя - это общее покрытие кода и скорость сборки.

    Стоит ли прилагать усилия к существующему решению, находящемуся в производстве?

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

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

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

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

    Что будет полезнее; потратить несколько недель на добавление тестов или несколько недель на добавление функциональности?

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

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

    Кроме того, добавление модульных тестов к существующей кодовой базе любого крупного проекта - это КРУПНАЯ задача, требующая приверженности и настойчивости.Вы не можете изменить что-то фундаментальное, ожидайте многого по пути и попросите своего спонсора не ожидать какой-либо рентабельности инвестиций, остановив поток ценности для бизнеса. Это не сработает, и, честно говоря, не должно.

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

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

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

    167
    ответ дан 24 November 2019 в 00:16
    поделиться
    • Стоит ли прилагать усилия к существующему решению, находящемуся в производстве?

    Да!

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

    Нет!

    • Что будет полезнее; потратить несколько недель на добавление тестов или несколько недель на добавление функций?

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

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

    Затем проведите тест для каждой текущей ошибки в вашей базе данных ошибок, который вызывает именно ошибку и который пройдет, когда ошибка будет исправлена. Тогда исправьте эти ошибки! : -)

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

    24
    ответ дан 24 November 2019 в 00:16
    поделиться

    Да. Нет. Добавление тестов.

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

    -2
    ответ дан 24 November 2019 в 00:16
    поделиться

    Да, может: просто попробуйте убедиться, что весь код, который вы пишете сейчас, проходит проверку.

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

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

    Это того стоит. В нашем приложении есть сложные правила перекрестной проверки, и недавно нам пришлось внести значительные изменения в бизнес-правила. У нас возникли конфликты, из-за которых пользователь не смог сохранить. Я понял, что на то, чтобы разобраться с этим в приложении, потребуется целая вечность (требуется несколько минут, чтобы добраться до того места, где были проблемы). Я хотел ввести автоматические модульные тесты и установить фреймворк, но я не сделал ничего, кроме пары фиктивных тестов, чтобы убедиться, что все работает. Имея в руках новые бизнес-правила, я начал писать тесты. Тесты быстро выявили условия, вызвавшие конфликты, и мы смогли разъяснить правила.

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

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

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

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

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

    • Сколько времени у вас уйдет на проверку всего этого кода? Дней? Недели? Месяцы? Годы?
    • Для кого вы пишете этот код? Платящие клиенты? Профессор? Проект с открытым исходным кодом?
    • Какой у вас график? У вас есть жесткие сроки, в которые вы должны уложиться? У вас вообще есть какие-то крайние сроки?

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

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

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

    Редактировать:

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

    Это похоже на вопрос: «Каковы плюсы и минусы использования системы контроля версий?» или "Каковы плюсы и минусы собеседования с людьми перед их приемом на работу?" или «Каковы плюсы и минусы дыхания?»

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

    13
    ответ дан 24 November 2019 в 00:16
    поделиться

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

    Здесь помните, что я говорю о добавлении модульных тестов выборочно, а не пытаюсь создать набор тестов, подобных тем, которые существовали бы, если бы вы практиковали TDD с самого начала. Поэтому, отвечая на вторую половину вашего второго вопроса: постарайтесь использовать TDD в своем следующем проекте, будь то новый проект или его переписывание (извините, но вот ссылка на другой книга, которую вам действительно стоит прочитать: Развитие объектно-ориентированного программного обеспечения с помощью тестов )

    Мой ответ на ваш третий вопрос такой же, как и на первый: он зависит от контекста вашего проекта.

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

    4
    ответ дан 24 November 2019 в 00:16
    поделиться

    Вы говорите, что не хотите покупать другую книгу. Так что просто прочтите статью Майкла Фезера о эффективной работе с устаревшим кодом . Тогда купите книгу :)

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

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

    • Как вы упомянули, когда вы обнаруживаете ошибку, самое время напишите тест (чтобы воспроизвести его), а затем исправьте ошибку. Если вы видите, что тест воспроизводит ошибку, вы можете быть уверены, что это хороший тест. Учитывая, что такая большая часть ошибок является регрессией (50%?), Почти всегда стоит писать регрессионные тесты.
    • Когда вы погружаетесь в область кода, чтобы изменить ее, самое время написать для нее тесты. В зависимости от характера кода подходят разные тесты. Один хороший набор советов можно найти здесь .

    OTOH, не стоит просто сидеть и писать тесты для кода, который нравится людям, особенно если никто не собирается его изменять. Это просто не добавляет ценности (кроме, возможно, понимания поведения системы).

    Удачи!

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

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

    Определите области проектов / модулей, в которых были повторно введены ошибки. Начните с этих проектов, чтобы писать тесты. Совершенно разумно писать тесты для новой функциональности и исправления ошибок.

    Стоит ли прилагать усилия для существующей решение, которое находится в производстве?

    Да. Вы увидите, как устраняются ошибки и упрощается обслуживание

    Не лучше ли игнорировать тестирование для этого проекта и добавьте его в Возможное будущее переписывание?

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

    Что будет полезнее; траты несколько недель добавление тестов или несколько недель на добавление функциональности?

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

    3
    ответ дан 24 November 2019 в 00:16
    поделиться

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

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

    3
    ответ дан 24 November 2019 в 00:16
    поделиться

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

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

    15
    ответ дан 24 November 2019 в 00:16
    поделиться
    • Да, это так. когда вы начинаете добавлять новые функции, это может вызвать некоторые модификации старого кода и в результате стать источником потенциальных ошибок.
    • (см. Первый), прежде чем вы начнете добавлять новые функции, весь (или почти) код (в идеале) должен быть покрыт модульными тестами.
    • (см. Первый и второй) :). новый грандиозный функционал может «разрушить» старый отработанный код.
    2
    ответ дан 24 November 2019 в 00:16
    поделиться

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

    0
    ответ дан 24 November 2019 в 00:16
    поделиться

    Хороших ответов так много, что я не буду повторять их содержание. Я проверил ваш профиль и похоже, что вы разработчик C # .NET. По этой причине я добавляю ссылку на проект Microsoft PEX и Moles , который может помочь вам с автогенерированием модульных тестов для устаревшего кода. Я знаю, что автогенерация - не лучший способ, но, по крайней мере, это способ начать. Посмотрите эту очень интересную статью из журнала MSDN об использовании PEX для устаревшего кода .

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

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

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

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

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

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

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

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

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

      • Предложение по продукту - Раньше я использовал бесплатный веб-продукт Junit Factory, но, к сожалению, сейчас он закрыт. Однако продукт продолжает существовать в коммерчески лицензированном генераторе AgitarOne JUnit Generator по адресу http://www.agitar.com/solutions/products/automated_junit_generation.html
    2. Для каждой исправляемой ошибки или добавляемой с этого момента функции используйте подход TDD, чтобы гарантировать, что новый код будет тестируемым, и поместите эти тесты в обычное дерево исходных текстов тестов.

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

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

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

    4
    ответ дан 24 November 2019 в 00:16
    поделиться

    Обновление

    Через 6 лет после первоначального ответа у меня немного другая точка зрения.

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

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

    Предыдущий ответ

    Я собираюсь поднять несколько бровей здесь :)

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

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

    Почему?

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

    2. Юнит-тесты стоят времени! А там, откуда я родом, это ценный товар - и бизнес обычно выбирает лучшую функциональность, а не полный набор тестов.

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

    4. Юнит-тесты не повлияют на воспринимаемое качество вашего продукта - качество, которое видит пользователь. Конечно, ваши методы могут работать точно так же, как они работали в первый день, интерфейс между презентационным и бизнес-слоем может быть безупречным - но знаете что? Пользователю все равно! Пригласите настоящих тестировщиков, чтобы они протестировали ваше приложение. И чаще всего эти методы и интерфейсы все равно придется менять, рано или поздно.

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

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

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

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

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

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

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

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

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

    Одним из первых вещей, которые мы сделали (после настройки сервера непрерывной сборки), было добавление регрессионных тестов. Это были сквозные тесты.

    • Каждый набор тестов начинается с инициализации базы данных в известное состояние. На самом деле у нас есть десятки наборов данных регрессии, которые мы храним в Subversion (в отдельном репозитории от нашего кода из-за огромного размера). FixtureSetUp каждого теста копирует один из этих наборов данных регрессии во временную базу данных, а затем запускается оттуда.
    • Затем установка тестового устройства запускает некоторый процесс, результаты которого нас интересуют. (Этот шаг является необязательным - некоторые регрессионные тесты существуют только для проверки отчетов.)
    • Затем каждый тест запускает отчет, выводит отчет в файл .csv и сравнивает содержимое этого .csv с сохраненным снимком. Эти CSV-файлы снимков хранятся в Subversion рядом с каждым набором данных регрессии. Если вывод отчета не соответствует сохраненному снимку, тест не пройден.

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

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

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

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

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

    Я добавлю свой голос и скажу да, это всегда полезно!

    Однако следует помнить о некоторых различиях: «черный ящик» и «белый ящик», единица измерения и функциональность. Поскольку определения различаются, вот что я подразумеваю под этим:

    • Черный ящик = тесты, написанные без специальных знаний о реализации, обычно проверяющие крайние случаи, чтобы убедиться, что все происходит так, как ожидает наивный пользователь. .
    • Белый ящик = тесты, написанные с знанием реализации, которые часто пытаются проверить известные точки отказа.
    • Модульные тесты = тесты отдельных модулей (функций, разделяемых модулей и т. д.). Например: убедитесь, что ваш класс массива работает должным образом, и что ваша функция сравнения строк возвращает ожидаемые результаты для широкого диапазона входных данных.
    • Функциональные тесты = тесты всей системы сразу. Эти тесты задействуют большую часть системы одновременно. Например: инициализировать, открыть соединение, сделать что-то реальное, закрыть, завершить. Мне нравится проводить различие между этими тестами и модульными тестами, потому что они служат другой цели.

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

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

    Как и другие, я также напомню вам о двух самых важных вещах, связанных с TDD:

    1. Создание тестов — это непрерывная работа. Он никогда не останавливается. Вы должны пытаться добавлять новые тесты каждый раз, когда пишете новый код или модифицируете существующий код.
    2. Ваш набор тестов никогда не бывает безошибочным! Не позволяйте тому факту, что у вас есть тесты, внушать вам ложное чувство безопасности. Тот факт, что он проходит набор тестов, не означает, что он работает правильно, или что вы не ввели тонкий регресс производительности и т. д.
    6
    ответ дан 24 November 2019 в 00:16
    поделиться

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

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

    Что будет полезнее; потратить несколько недель на добавление тестов или несколько недель на добавление функциональности?
    Для новой функциональности (кода) это просто. Сначала вы пишете модульный тест, а затем функциональность. Для старого кода вы решаете по пути. Вам не обязательно иметь все модульные тесты на месте... Добавьте те, отсутствие которых вам больше всего мешает... Время (и ошибки) покажет, на каком из них вы должны сосредоточиться;)
    2
    ответ дан 24 November 2019 в 00:16
    поделиться
    Другие вопросы по тегам:

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