Есть две причины для написания тестов:
- Утверждение ожидаемого поведения
- Предотвращение регресса поведения
Подход к (1) утверждению ожидаемого поведения:
Когда вы утверждаете ожидаемое поведение, вы хотите убедиться, что код работает так, как вы думаете. По сути, это автоматизированный способ выполнения рутинной ручной проверки, которую может выполнить любой разработчик при реализации любого вида кода:
- Работает ли то, что я только что написал?
- Действительно ли этот цикл заканчивается?
- Это зацикливается в том порядке, в котором я думаю?
- Будет ли это работать для нулевого ввода?
На эти вопросы мы все отвечаем в уме, и обычно мы пытаемся выполнить код и в голове, чтобы убедиться, что он работает. В таких случаях часто бывает полезно, чтобы компьютер ответил на них определенным образом. Итак, мы пишем модульный тест, который утверждает, что это так. Это дает нам уверенность в нашем коде, помогает нам находить дефекты на раннем этапе и даже может помочь в реализации кода.
Это хорошая идея - делать это там, где вы считаете необходимым. Любой код, который немного сложен для понимания или нетривиален. От этого может выиграть даже тривиальный код. Все дело в вашей уверенности. Как часто это делать и как далеко идти, будет зависеть от вашего собственного удовлетворения. Остановитесь, когда сможете уверенно ответить «да» на вопрос: «Вы уверены, что это работает?»
Для этого вида тестирования вам не важны видимость, интерфейсы или что-то еще, вас волнует только рабочий код. Итак, да, вы бы протестировали частные и защищенные методы, если бы почувствовали, что их нужно протестировать, чтобы вы ответили «Да» на вопрос.
Подход (2) Предотвращение регресса поведения:
После того, как у вас есть рабочий код, вам понадобится механизм для защиты этого кода от будущих повреждений. Если бы никто и никогда больше не касался вашего источника и вашей конфигурации, вам бы это не понадобилось, но в большинстве случаев вы или другие будут касаться источника и конфигураций вашего программного обеспечения. Эта внутренняя возня с большой вероятностью нарушит ваш рабочий код.
В большинстве языков уже существуют механизмы защиты от этого ущерба. Функции видимости - это один механизм. Частный метод изолирован и скрыт. Инкапсуляция - это еще один механизм, при котором вы разделяете вещи на части, чтобы изменение других частей не влияло на другие.
Общий механизм для этого называется: кодирование до границы. Создавая границы между частями кода, вы защищаете все внутри границы от вещей за ее пределами. Границы становятся точкой взаимодействия и контрактом, по которому взаимодействуют вещи.
Это означает, что изменения границы, либо путем нарушения интерфейса, либо нарушения его ожидаемого поведения, могут повредить и, возможно, нарушить другие границы, которые от него зависят. Вот почему рекомендуется иметь модульный тест, нацеленный на эти границы и утверждающий, что они не меняются семантически и в поведении.
Это ваш типичный модульный тест, о котором все говорят, когда упоминают TDD или BDD. Дело в том, чтобы ужесточить границы и защитить их от изменений. Вы не хотите тестировать частные методы для этого, потому что частный метод не является границей. Защищенные методы - это ограниченная граница, и я бы защищал их. Они не открыты миру, но все же подвержены воздействию других отсеков или «Единиц».
Что с этим делать?
Как мы видели, есть веская причина для модульного тестирования общедоступных и защищенных методов, чтобы утверждать, что наши интерфейсы не меняются. Также есть веская причина протестировать частные методы, чтобы убедиться, что наша реализация работает. Так следует ли нам проводить модульное тестирование их всех?
Да и нет.
Во-первых : протестируйте все методы, которые, по вашему мнению, необходимы для окончательного доказательства того, что они работают в большинстве случаев, чтобы быть уверенным в том, что ваш код работает независимо от видимости. Затем отключите эти тесты. Они сделали там работу.
Наконец : напишите тесты для ваших границ. Проведите модульный тест для каждой точки, которая будет использоваться другими модулями вашей системы. Убедитесь, что этот тест подтверждает семантический контракт, имя метода, количество аргументов и т. Д. А также убедитесь, что тест подтверждает доступное поведение модуля. Ваш тест должен продемонстрировать, как использовать устройство и на что он способен. Оставьте эти тесты включенными, чтобы они запускались при каждом нажатии кода.
ПРИМЕЧАНИЕ. Причина, по которой вы отключили первый набор тестов, состоит в том, чтобы позволить провести рефакторинг. Активный тест - это комбинация кода. Это предотвращает будущую модификацию кода, который он тестирует. Это нужно только для ваших интерфейсов и контрактов на взаимодействие.