Как проверить последовательность вызовов функций в C?
Я использую Gtest для выполнения модульного тестирования на модуль C. Одним из требований является проверка того, что Supervision_Log()
вызывается после выполнения нескольких различных функций. Файл C включает в себя следующее:
void MainFunction (void)
{
.
.
.
/*Some code*/
.
.
.
ModeMonitoring();
RadarStatusMonitoring();
CameraStatusMonitoring();
Supervision_Log(ModeManager);
}
Я узнал, что в CppUTest есть объект, который называется mock().strictOrder()
это делает то, что мне нужно. Но есть ли подобные вещи в Gtest? или что мне делать?
PS: нам нужно поставить тестовый случай, который не удастся, если кто-то изменил порядок вызовов функций. Этот контрольный пример будет действовать в качестве опекуна для этого заказа от любых изменений в будущих выпусках.
2 ответа
Для модульного тестирования вы должны использовать утилиту покрытия кода gcov, которая сообщает вам, какая часть кода выполнена, а какая - нет, а также предоставляет отчет о том, сколько раз вызывается данная функция, но вам нужно создать код с флагом покрытия кода.
- Вы должны изменить тестируемый код, чтобы вы могли внедрить зависимость. Это можно сделать с помощью статического или динамического полиморфизма (обычно я делаю микс, но для простоты давайте сделаем динамический полиморфизм):
class IDependency {
public:
virtual ~IDependency() {}
virtual void ModeMonitoring() = 0;
virtual void RadarStatusMonitoring() = 0;
virtual void CameraStatusMonitoring() = 0;
virtual void Supervision_Log(const ModeManagerType&) = 0;
};
class ProductionDependency : public IDependency {
public:
void ModeMonitoring() override {
::ModeMonitoring();
}
void RadarStatusMonitoring() override {
::RadarStatusMonitoring();
}
void CameraStatusMonitoring() override {
::CameraStatusMonitoring();
}
void Supervision_Log(const ModeManagerType& x) override {
::Supervision_Log(x);
}
};
ProductionDependency productionDependency;
void MainFunction(IDependency& dep = productionDependency)
{
// ....
dep.ModeMonitoring();
dep.RadarStatusMonitoring();
dep.CameraStatusMonitoring();
dep.Supervision_Log(ModeManager);
}
- Затем в тесте создайте макет для зависимости:
class MockDependency : public IDependency {
public:
MOCK_METHOD(void, ModeMonitoring, (), (override));
MOCK_METHOD(void, RadarStatusMonitoring, (), (override));
MOCK_METHOD(void, CameraStatusMonitoring, (), (override));
MOCK_METHOD(void, Supervision_Log, (const ModeManagerType&), (override));
};
- Наконец, в тестовом экспресс-заказе:
TEST(MainFunction, callsInOrder)
{
MockDependency dep;
Expectation modeMonitoring = EXPECT_CALL(dep, ModeMonitoring());
EXPECT_CALL(dep, CameraStatusMonitoring()).After(modeMonitoring); // here order is forced
EXPECT_CALL(dep, RadarStatusMonitoring());
EXPECT_CALL(dep, Supervision_Log(_));
MainFunction(dep);
}
Вот документ о After.
Пожалуйста, не указывайте в строгом порядке. Убедитесь, что только требуемый порядок ограничен тестом, например, заказ, требуемый внешним API. Не указывайте порядок всех вызовов на основе текущей реализации, так как это ограничит ваши возможности рефакторинга.
Вот живая демонстрация.