Загуглите фразу ” должен ли я тестировать частные методы “, и вы получите целый ряд мнений, которые сводятся к “нет”. К счастью, я здесь для того, чтобы сказать, что тестировать частные методы можно.
Что в этом Такого Особенного?
В данный момент я готовлюсь преподавать курс программного обеспечения в своем университете, и я работал над служебным классом на Java, в котором было множество частных вспомогательных методов. В моем конкретном случае на самом деле не было никаких открытых общедоступных методов, кроме main
, и я нахожу сложным писать тесты, которые взаимодействуют с входными потоками. В результате я захотел написать несколько тестов JUnit, чтобы доказать функциональность частных методов.
Однако, когда я обратился к Google, я обнаружил, что большинство экспертов советуют не тестировать частные методы:
- Почему тестирование белого ящика не рекомендуется в ООП?
- Следует Ли Тестировать Частные Методы?
- Как вы проводите модульное тестирование частных методов?
- Проводите ли вы модульное тестирование частных методов?
Вместо этого они утверждают, что мы должны протестировать наши общедоступные методы, которые вызывают наши частные методы. В следующих подразделах я попытаюсь разобрать их аргументы.
Частные Методы – Это Детали Реализации
Распространенным аргументом против тестирования частных методов является то, что частные методы являются деталями реализации:
Закрытый метод – это деталь реализации, которая должна быть скрыта от пользователей класса. Тестирование частных методов нарушает инкапсуляцию.
джоп , 2008
Другими словами, то, как реализуется решение, не имеет значения с точки зрения тестирования. В конечном счете, мы хотим протестировать наше решение на основе его ожидаемого поведения для пользователя.
Тесты Частного Метода Хрупки
Поскольку частные методы являются деталями реализации, мы можем изменять эти детали практически без каких-либо затрат для нас. Однако, если мы решим протестировать наши частные методы, мы рискуем нарушить наши тесты. В результате наши тесты становятся хрупкими, что означает, что они легко ломаются. На самом деле, я думаю, что пользователь Stack Overflow сказал это лучше всего:
Проблема здесь в том, что эти “будущие изменения кода” неизменно означают рефакторинг внутренней работы некоторого класса. Это происходит так часто, что написание тестов создает барьер для рефакторинга.
Программист-преступник , 2008
Другими словами, хрупкие тесты могут препятствовать рефакторингу, что создает барьер для улучшения кода.
Сбои В Тестировании Частного Метода Могут Не Иметь Значения
Один из наиболее интересных аргументов, которые я видел, звучит примерно так:
Если вы не можете взломать общедоступный метод, действительно ли имеет значение, что делают частные методы?
Установка , 2012
Другими словами, мы можем быть в состоянии взломать наши частные методы, но открытые методы могут находиться под различными ограничениями, которые приводят к тому, что ошибка в частном методе никогда не проявляется.
Пример для тестирования частных методов
В целом, я согласен со всеми аргументами против тестирования частных методов. На самом деле, если бы я не столкнулся со своими собственными потребностями в тестировании частных методов, я мог бы оказаться по ту сторону забора. Однако, как всегда, проблема немного более тонкая.
Общедоступные методы Зависят от деталей реализации
Когда мы приводим аргумент о том, что мы не должны заботиться о деталях реализации, мы рискуем пропустить крайние случаи, когда наши общедоступные методы выходят из строя. Другими словами, знание того, как наша система спроектирована под капотом, имеет решающее значение для обеспечения ее правильной работы. Как бы мы доказали, что это работает иначе?
В качестве своего рода глупого примера представьте себе метод последовательности Фибоначчи, который выводит член в последовательности на основе некоторого индекса. Если мы протестируем этот метод, как мы узнаем, сколько входных данных нужно попробовать, чтобы убедиться, что метод работает? При тестировании черного ящика нам пришлось бы попробовать их все. При тестировании “белого ящика” (которое зависит от деталей реализации) нам просто нужно было бы пройти все ветки.
Конечно, я не думаю, что кто-то выдвигает аргумент о том, что общедоступные методы не должны тестироваться в белых ящиках, но это подводит меня ко второму пункту: тесты общедоступных методов такие же хрупкие, как и тесты частных методов, и они часто раздуты.
Тесты Общедоступных Методов Являются Хрупкими и Часто Раздутый
Поскольку тесты частных методов зависят от деталей реализации, возможно, что тесты будут прерываться по мере изменения требований. Тем не менее, я не уверен, что публичные методы также ясны в этом отношении.
Например, иногда методы могут влиять на состояние объекта. Обычно мы вызываем эти методы экземпляра, потому что они напрямую взаимодействуют с экземпляром объекта. Чтобы протестировать метод экземпляра, нам обычно приходится настраивать состояние этого объекта, чтобы мы могли отслеживать его поведение при вызове этого метода.
Поскольку мы застряли на использовании общедоступных методов для настройки вашего объекта во время тестирования, мы можем столкнуться со сценарием, в котором тесты зависят от поведения нескольких методов — не обязательно тестируемого метода. Если бы у нас был доступ к частным методам (например, установщикам), мы могли бы установить состояние объекта, не становясь зависимыми от других общедоступных методов, которые могут работать, а могут и не работать.
Что еще хуже, тестирование в белых ящиках превращается в кошмар. Внезапно нам приходится вводить всевозможные данные в наш общедоступный API в надежде, что мы сможем получить надлежащее покрытие кода. Было бы намного проще протестировать частные методы напрямую и отбросить эти тесты, когда эти частные методы больше не нужны.
Что касается только удобочитаемости, представьте, что вы пытаетесь назвать более 50 уникальных тестов для одного метода. После нескольких раундов рефакторинга вы даже не будете знать, какие тесты стоит удалить. Тесты с использованием частных методов обеспечивают четкое разделение ответственности.
Наконец, представьте, что вы осуждаете общедоступный метод, поддерживаемый более чем 50 тестами. Мало того, что все эти тесты пропадают впустую, но и ошибка заниженной стоимости в основном гарантирует, что мы откажемся осуждать общедоступный метод из-за количества тестов, стоящих за ним. Импульс накопленных тестовых примеров сам по себе помешает нам улучшить наш код.
Ошибки тестирования Частного Метода Имеют значение
В конечном счете, мы приходим к последнему аргументу: если публичные методы работают, кого волнует, что делают частные методы? Другими словами, пока API работает, кого волнует, провалит ли какая-то внутренняя функция какой-то тест или нет. По крайней мере, я чувствую, что здесь выдвигается именно такой аргумент, верно?
Для меня сбои в тестировании частного метода должны иметь значение, потому что эта ошибка может просто проявиться в дальнейшем. В конце концов, кодирование – это динамичный процесс. Другими словами, основная проблема может не проявиться сегодня, но она может появиться только через 3 версии. В результате активное игнорирование частного метода, в котором может быть ошибка, – это бомба замедленного действия.
Кроме того, я также не являюсь поклонником настроений, вызванных этим аргументом. Честно говоря, я бы очень беспокоился, если бы такие же аргументы были выдвинуты в других инженерных дисциплинах. Например, я бы надеялся, что производители самолетов тщательно протестируют свое оборудование, даже если у них будет тройное резервирование на случай сбоев.
Тем не менее, я действительно нахожу первоначальный аргумент наиболее убедительным. Мы можем обсуждать достоинства тестирования частных методов весь день, но многие программы просто не являются критически важными. В современном мире программное обеспечение развивается быстро, и, вероятно, достаточно тестирования общедоступных методов. Черт возьми, я бы предпочел это телеметрии.
Это нормально – тестировать Частные методы
Когда я решил написать эту статью, это было в ответ на огромное количество литературы в Интернете, в которой говорится, что тестирование частных методов – плохая идея. Честно говоря, мне это показалось немного странным. В конце концов, я бывал в ситуациях, когда открытый метод построен на слоях частных методов, поэтому тестирование открытого интерфейса становится действительно неэффективным способом изоляции ошибок. Другими словами, откуда мы знаем, как написать правильный тест для выполнения всех ветвей в каком-то базовом частном методе?
В любом случае, действительно ли практично тестировать частные методы – это совершенно другой вопрос, но я бы не стал заходить так далеко, чтобы сказать, что тестирование частных методов хорошо или плохо. Как и во многих дискуссиях в области компьютерных наук, этот вопрос более тонкий.
Конечно, в процессе написания этой статьи я также работал над приложением в Kotlin и обнаружил, что гораздо практичнее тестировать только общедоступный API. В конце концов, все лежащие в основе частные методы были очень маленькими, и о них было легко рассуждать. Однако я не могу сказать то же самое о каждом проекте, который я написал, поэтому я оставляю выбор за вами: делайте то, что имеет смысл, и ничего больше.
Прямо сейчас имеет смысл стать премиум-участником Renegade Coder ! С премиум-подпиской вы получите полный доступ к блогу, чтобы узнать меня немного лучше. Если вам нужно больше времени, чтобы разобраться во всем, ознакомьтесь с некоторыми из следующих статей:
- Поведение
i=i++
в Java - Как преподавать массивы в информатике
Пока вы здесь, почему бы не поделиться тем, что вы думаете о тестировании частных методов? Вы строго избегаете этого, или в их ситуациях, по вашему мнению, это имеет смысл?
Сообщение Это нормально – тестировать частные методы появились сначала на/| Программист-отступник .
Оригинал: “https://dev.to/renegadecoder94/it-s-okay-to-test-private-methods-1dj9”