Издевательство над невиртуальными методами в C ++ без редактирования производственного кода?

StackOverflow https://stackoverflow.com/questions/2339558

Вопрос

Я довольно новый разработчик программного обеспечения, в настоящее время работаю над добавлением модульных тестов к существующему проекту на C ++, который начался много лет назад.По нетехнической причине мне не разрешено изменять какой-либо существующий код.Базовый класс всех моих модулей имеет множество методов для настройки / получения данных и взаимодействия с другими модулями.

Поскольку я просто хочу провести модульное тестирование каждого отдельного модуля, я хочу иметь возможность использовать стандартные значения для всех моих методов межмодульной связи.То есть.для метода Ping(), который проверяет, активен ли другой модуль, я хочу, чтобы он возвращал true или false в зависимости от того, какой тест я выполняю.Я изучал Google Test и Google Mock, и они действительно поддерживают насмешливые невиртуальные методы.Однако описанный подход (http://code.google.com/p/googlemock/wiki/CookBook#Mocking_Nonvirtual_Methods) требует, чтобы я "шаблонизировал" исходные методы для использования либо реальных, либо макетных объектов.Я не могу пойти и шаблонизировать свои методы в базовом классе из-за требования, упомянутого ранее, поэтому мне нужен какой-то другой способ издевательства над этими виртуальными методами

По сути, методы, которые я хочу смоделировать, находятся в некотором базовом классе, модули, которые я хочу модульно протестировать и создать макеты, являются производными классами этого базового класса.Существуют промежуточные модули между моим базовым классом модулей и модулями, которые я хочу протестировать.

Я был бы признателен за любой совет!

Спасибо,

JW

Редактировать:Более конкретные примеры

Мой базовый класс - скажем, rootModule, модуль, который я хочу протестировать, - leafModule .Существует промежуточный модуль, который наследуется от rootModule, leafModule наследуется от этого промежуточного модуля.

В моем leafModule я хочу протестировать метод doStuff() , который вызывает невиртуальный GetStatus(moduleName), определенный в классе rootModule.Мне нужно каким-то образом заставить GetStatus() возвращать выбранное сохраненное значение.Насмешка для меня в новинку, так является ли использование макетных объектов вообще правильным подходом?

Это было полезно?

Решение

Я бы написал скрипт на Perl / Ruby / Python для чтения в исходном дереве исходных текстов и выписал бы издевательское дерево исходных текстов в другой каталог.Вам не обязательно полностью разбирать C ++, чтобы заменить определение функции.

Другие советы

Существует несколько различных способов замены невиртуальных функций.Один из них заключается в том, чтобы повторно объявить их и скомпилировать новый тестовый исполняемый файл для каждого отдельного набора невиртуальных функций, которые вы хотели бы протестировать.Это вряд ли масштабируемо.

Второй вариант - сделать их виртуальными для тестирования.Большинство компиляторов позволяют вам определять что-либо в командной строке, поэтому скомпилируйте свой код с помощью -DTEST_VIRTUAL=virtual или -DTEST_VIRTUAL, чтобы сделать их либо виртуальными, либо обычными, в зависимости от того, тестируется он или нет.

Третий вариант, который может быть полезен, - это использовать mocking framework, который позволяет вам имитировать невиртуальные функции.Я автор HippoMocks (отказ от ответственности в отношении нейтральности и так далее), И недавно мы добавили возможность издеваться над простыми функциями C на платформах X86.Это может быть распространено на невиртуальные функции-члены с небольшой доработкой, и это будет то, что вы ищете.Имейте в виду, что, если ваш компилятор может видеть как использование, так и определение функции одновременно, он может встроить ее и что имитация может завершиться неудачей.Это справедливо, в частности, для функций, которые определены в заголовках.

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

Один из подходов заключался бы в указании различных источников для тестирования.Допустим, ваша производственная цель использует rootModule.h и rootModule.cpp.Используйте разные источники для вашей цели тестирования.Вы можете указать другой заголовок, изменив свой путь включения, чтобы #include "rootModule.h" фактически загружал unittest/rootModule.h.Затем издевайтесь над rootModule сколько душе угодно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top