Как вы издеваетесь над функцией, которая является частью тестируемого класса gmock?

Я использую googletest/googlemock (GTest/GMock). Я могу протестировать приведенный ниже код только тогда, когда Selection естественным образом возвращает false. Как бы я смоделировал приведенный ниже пример проблемы?

У меня возникают трудности с изменением возвращаемого значения selection, потому что он использует реальный код.

class frame
{
    bool Selection();
    void Actions();
};

void frame::Action()
{
    if (Selection())
    {
        // do something
    }
    else
    {
        // do something else
    }
}

void WrapAction()
{
    Frame->Action();
}

TEST_F(UITest, ActionWithSelectionTrue)
{
    EXPECT_CALL(*Frame, Selection()).WillOnce(Return(true));

    WrapAction();
}

TEST_F(UITest, ActionWithSelectionFalse)
{
    EXPECT_CALL(*Frame, Selection()).WillOnce(Return(false));
    WrapAction();
}

person rafael gonzalez    schedule 28.02.2019    source источник
comment
Вы должны тестировать поведение, а не строки кода. Не пытайтесь нарушить целостность класса. У него есть своя работа - пусть она выполняет свою работу и в тестах. Используйте свой класс в тестах так же, как его должен использовать любой другой пользователь. Подумайте, при каком условии Selection() может вернуть true/false? Как вы можете привести свой класс в такое состояние, используя только общедоступные функции?   -  person Yksisarvinen    schedule 28.02.2019
comment
Поскольку тестируемый класс frame не имеет зависимостей, нечего издеваться, поэтому EXPECT_CALL бесполезен.   -  person Marek R    schedule 28.02.2019


Ответы (1)


Традиционные модульные тесты имеют форму A3:

  1. Собрать (также называется "Упорядочить"; настроить тестируемый объект)
  2. Действовать (выполнить желаемое действие над объектом)
  3. Утвердить (подтвердить правильность изменения значений, отправки событий и т. д.)

Это допустимая форма для тестов, и она вообще не требует фиктивной среды.

В тесте с макетами вам может (в зависимости от того, как работает ваша библиотека макетов) изменить эту процедуру на A4:

  1. Ассемблировать (включая внедрение фиктивных зависимостей)
  2. Предвидеть (устанавливать ожидания в отношении фиктивных зависимостей, определяя ожидаемые вызовы, задавая возвращаемые значения, побочные эффекты и т. д.)
  3. Действовать
  4. Утверждать (может нечего больше утверждать, если фиктивные ожидания покрывают все).

В вашем случае непонятно, над чем вы издеваетесь. Где находятся зависимости, которые вы внедряете и заменяете имитациями?

Учитывая код, который вы нам показали, я думаю, вам следует использовать тестовый шаблон A3. Это будет означать, что в разделе «Сборка» вы настраиваете объект, задавая выбор, затем выполняете над ним свое действие и проверяете результат.

Если вы не можете работать с шаблоном A3, возможно, вам нужно провести рефакторинг, чтобы лучше разделить зависимости. Когда вы это сделаете, вы сможете смоделировать и протестировать шаблон A4.

person metal    schedule 28.02.2019
comment
внутренняя функциональность выбора зависит от последовательного соединения, он возвращает true или false в зависимости от того, подключено устройство или нет. я постараюсь реорганизовать код, чтобы не все было в одном классе. это просто очень сложно сделать, потому что код изначально был написан без каких-либо модульных тестов. если я изменю что-то одно, это сломает все остальное. - person rafael gonzalez; 28.02.2019
comment
Это идеальный случай для внедрения зависимостей — у вас есть зависимость от последовательного порта. Для рефакторинга вы должны внедрить объект, который имитирует поведение последовательного порта (или, возможно, функции более высокого уровня, такие как проверка готовности данных и получение их независимо от канала этих данных), затем в тесте вы можете контролировать, что объект при тестировании, манипулируя фиктивным последовательным портом, а затем проверяя ответы объекта. В этом случае вам нужен тестовый шаблон A4. - person metal; 28.02.2019