Написание юнит-тестов в середине

14

Является ли юнит-тестирование 100% -ной сделкой?

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

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

Лионель
источник

Ответы:

14

Любые юнит-тесты лучше, чем ничего. Так что это не сделка "все или ничего".

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

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

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

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

Йосек
источник
3

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

Весь новый код должен иметь модульные тесты.

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

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

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

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

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

  3. Напишите тесты, чтобы по возможности охватить функциональность кода, который вы собираетесь изменить. Регулярно регистрируйтесь и проверяйте все изменения.
  4. Написать тесты для новой функциональности / изменения функциональности.
  5. Реализуйте функциональность (это ваш обычный цикл TDD)
  6. Обязательно проведите рефакторинг областей, которые вы охватили тестами (красный-зеленый-рефакторинг).

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

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

flamingpenguin
источник
2

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

phant0m
источник
2

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

user281377
источник
+1 «новые части, скорее всего, содержат ошибки»
МВД
Это зависит от сложности проекта. «Работать нормально» обычно означает «не сломался недавно» или «не сломался так, как кто-либо упомянул» ... не для того, чтобы предлагать вам всегда писать модульные тесты для существующего кода, но не предполагайте что он работает правильно или как задумано, либо.
Дейв ДюПлантис
1

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

Алексей Ануфриев
источник
0

Является ли юнит-тестирование 100% -ной сделкой?

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

Марси
источник