Вы начинаете юнит-тестирование с непосредственного перехода к некоторым нетривиальным вопросам.
Вопрос 1: Как обращаться с деталями реализации / частными функциями? Ответ: Юнит-тестированиепоиск ошибок в вашем коде, и это одна из основных задач модульного тестирования (и большинства других видов тестирования).Другая основная цель - предотвратить появление ошибок, выполняя роль регрессионных тестов при изменении программного обеспечения.Ошибки есть в реализации - разные реализации идут с разными ошибками.Поэтому обязательно проверьте детали реализации.Одним из важных инструментов для поддержки здесь является анализ покрытия, который показывает, какие части кода реализации были достигнуты вашими тестами.
Вы можете даже протестировать аспекты, выходящие за рамки контракта функции: a) Отрицательные тесты - это тестыкоторые намеренно проверяют поведение на наличие неверных / неуказанных входных данных и важны для обеспечения безопасности системы.Поскольку даже при наличии неверного ввода система не должна быть взломана, например, из-за чтения или записи за пределы памяти.Это, однако, вероятно, не относится к вашему примеру, потому что ваш метод, скорее всего, предназначен для реализации «полной функции», а не «частичной функции».b) Тесты деталей реализации (если они доступны) могут быть даже выполнены за пределами того, что требуется для текущей реализации.Это может быть сделано для предотвращения ошибок в будущих изменениях компонента, таких как расширения API.
Однако существуют и вторичные цели модульного тестирования.Один из них заключается в том, чтобы избежать ненужных сбоев ваших тестов при изменении деталей реализации.Один из подходов к достижению вторичной цели состоит в тестировании деталей реализации через общедоступный API.Таким образом, некоторые виды перепроектирования деталей реализации не будут нарушать ваши тесты: переименование, разбиение или объединение частных функций не повлияет на тесты.Однако переключение на другой алгоритм, вероятно, потребует от вас переосмысления ваших тестов: тесты для итеративной / рекурсивной реализации функции Фибоначчи будут выглядеть иначе, чем для реализации, использующей выражение закрытой формы из Moivre / Binet, илидля реализации таблицы поиска.
Для вашего примера это означает, что вы должны попытаться проверить функциональность вашей частной функции через публичный API.
Вопрос 2: Как поступитьс зависимостями от других частей программного обеспечения? Модульное тестирование фокусируется на поиске ошибок в небольших изолированных фрагментах кода.Когда эти фрагменты кода имеют зависимости от других частей кода, это может негативно повлиять на вашу способность правильно их тестировать.Но действительно ли это так, зависит от фактической зависимости.Например, если в вашем коде используется функция Math.sin()
, это также зависимость от другой части кода, но такая зависимость, как правило, не вредит вашей способности правильно тестировать код.
Зависимости от других компонентовбеспокоит вас в следующих случаях: использование других компонентов затрудняет стимулирование всех интересных сценариев в тестируемом коде.Или использование другого компонента приводит к недетерминированному поведению (время, случайность, ...).Или использование других компонентов приводит к недопустимо долгому времени сборки или выполнения.Или другой компонент глючит или даже еще не доступен.
Если все эти критерии не выполнены (как это обычно бывает с функцией Math.sin()
), вы обычно можете просто жить с другимкомпоненты, являющиеся частью ваших испытаний.Однако вы должны помнить, что в своих модульных тестах вы по-прежнему сосредотачиваетесь на ошибках в своем коде и не начинаете писать тесты, которые фактически тестируют другие компоненты: имейте в виду, что другие компоненты имеют свои собственные тесты.
В вашем примере вы выбрали Outerclass
, чтобы иметь некоторые очевидно тривиальные функции.В этом случае вы можете жить с Outerclass, просто оставаясь частью ваших тестов.Тем не менее, это только пример с вашей стороны - действительно другой класс может на самом деле мешать в соответствии с вышеуказанными критериямиЕсли это так, то вам каким-то образом придется управлять этой зависимостью, которая требует, чтобы все каким-то образом пришли к дизайну, удобному для тестирования.
Здесь есть целое семейство подходов, так что вылучше искать в Интернете «дизайн для тестируемости» и «инверсия контроля».Кроме того, вы также должны попытаться узнать о том, что отличает модульное тестирование и интеграционное тестирование: это поможет вам избежать попыток применить модульное тестирование к частям кода, которые лучше тестировать с интеграционным тестированием.