Часто части интерфейсов предназначены для использования только в определенных контекстах (только во время конфигурации, только во время инициализации, только из определенных потоков, только из тестового кода, только в определенных состояниях системы, ...).Возможности языков программирования выражать это так, что создаются реальные технические барьеры, довольно ограничены (обычно у вас есть публичные и частные, часто защищенные, иногда немного больше) - и достаточно часто существуют приемы для преодоления барьеров, таких как публичные или частные декларации,например, в C ++ с использованием приемов препроцессора, в Java и аналогичных языках с использованием самоанализа.Например, в Python такие механизмы полностью заменены соглашениями - если вы не будете следовать им, рано или поздно вы потеряете.
Рассмотрение вещей с точки зрения, не ориентированной на конкретный язык программирования.поэтому предпочтительнее рассматривать public
, private
и т. д. в качестве логических понятий, представляющих архитектурные ограничения.Например, выделение некоторых частных функций, представляющих подробности реализации, в отдельный класс в качестве открытых методов не меняет их природу того, чтобы быть деталями реализации: тогда этот другой класс, безусловно, не должен использоваться другими компонентами, а также тестовый код, использующий этот класс.не менее затронуты, если эти детали реализации изменятся.Я упоминаю об этом только для того, чтобы продемонстрировать, что я не вижу большой разницы в том, чтобы сделать метод общедоступным, но сказать другим не использовать метод по сравнению с извлечением его в другой класс и запретить другим использовать этот класс.
В вашем случае вы хотели бы указать, что определенные функции должны рассматриваться как подробности реализации (private
), но все же должны быть доступны для целей модульного тестирования.И, да, я согласен с тем, что может иметь больше смысла тестировать функции private
напрямую, чем тестировать их косвенно на уровне обслуживания.Это, конечно, компромисс, но из моего опыта я также знаю такие случаи.
Самый простой подход (если язык, который вы используете, не предлагает никаких лучших трюков, таких как конструкция C ++ friend
), как вы предложили, чтобы сделать методы общедоступными и документировать, что они не предназначены для использования.Если вы хотите сделать это более заметным, одна из возможностей - сделать функцию общедоступной, но выразить ограничения в использовании путем именования.Функция foo
, которая должна использоваться только в тестах, может быть названа forTestingOnly_foo
.Так как это делает также уродливым, когда функция вызывается в частном контексте, foo
все еще может быть закрытой функцией с не приватной оболочкой forTestingOnly_foo
.
Если вы можете установить соглашение об именах для такихВ сценариях вы можете создать простой инструмент проверки, который проверяет, что никто (кроме как из контекста тестирования) не обращается к любому из этих «общедоступных, но логически закрытых» методов, и использовать его в сборке, чтобы он не работал в случае обнаружения неправильного использования.Необходимость таких подходов во многом зависит от организационной культуры, в которой вы работаете.