pImpl идиома и Тестируемость

pImpl идиома в C++ имеет целью скрывать детали реализации (=private участники) класса от пользователей того класса. Однако это также скрывает некоторые зависимости того класса, который обычно расценивается плохо с точки зрения тестирования.

Например, если класс A скрывает свои детали реализации в Классе AImpl, который только доступен от A.cpp, и AImpl зависит от большого количества других классов, это становится очень трудным к классу A модульного теста, так как среда тестирования не имеет никакого доступа к методам AImpl и также никакого способа ввести зависимость в AImpl.

Кто-либо столкнулся с этой проблемой прежде? и Вы нашли решение?

- редактирование-

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

17
задан Rimo 7 May 2010 в 00:16
поделиться

3 ответа

Идея pimpl заключается не столько в том, чтобы скрыть детали реализации от классов (частные члены уже это делают), но в том, чтобы вынести детали реализации из заголовка. Проблема в том, что в модели включений C ++ изменение частных методов / переменных приведет к перекомпиляции любого файла, включающего этот файл. Это боль, и поэтому pimpl стремится избавиться от нее. Это не помогает предотвратить зависимости от внешних библиотек. Это делают другие техники.

Ваши модульные тесты не должны зависеть от реализации класса. Они должны убедиться, что ваш класс действительно действует так, как должен. Единственное, что действительно имеет значение, - это то, как объект взаимодействует с внешним миром. Любое поведение, которое ваши тесты не могут обнаружить, должно быть внутренним по отношению к объекту и, следовательно, не иметь отношения к делу.

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

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

16
ответ дан 30 November 2019 в 10:49
поделиться

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

Юнит-тестирование должно быть связано только с публичным интерфейсом, который открывает класс A; то, что A делает внутри с зависимостями, вас не касается. До тех пор, пока все инжектируется правильно, вы должны быть в состоянии передавать макеты без необходимости беспокоиться о внутренней реализации A. В некотором смысле, можно сказать, что тестируемость и правильный pImpl идут рука об руку, поскольку нетестируемая реализация скрывает детали, которые не должны быть скрыты.

11
ответ дан 30 November 2019 в 10:49
поделиться

Почему модульному тесту нужен доступ к внутренним компонентам реализации A?

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

Если Aimpl генерирует побочные эффекты, которые вам нужно протестировать, это указывает на то, что вам следует взглянуть на свой дизайн.

17
ответ дан 30 November 2019 в 10:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: