Пересмешивать не виртуальные методы в C ++ без редактирования рабочего кода? - PullRequest
19 голосов
/ 26 февраля 2010

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

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

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

Буду признателен за любые советы!

Спасибо,

JW

РЕДАКТИРОВАТЬ: более конкретные примеры

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

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

Ответы [ 3 ]

13 голосов
/ 18 мая 2010

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

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

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

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

3 голосов
/ 26 февраля 2010

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

1 голос
/ 26 февраля 2010

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

...