В настоящее время я пытаюсь оценить различные рамки тестирования. Когда я использую фальшивые фреймворки (я склоняюсь к FakeIt, но гугл-макет тоже хорош), я знаю, что вы можете провести собственное тестирование «производительности», используя вызовы таймера ОС до и после вызова функции для проверки производительности функции. Это не то, что я после.
То, что у меня есть, это классы, которые реализуют задержки на выходах при определенных входах. Например:
Я хотел бы иметь возможность сделать что-то, где я указываю границу:
myMock.theInput();
EXPECT_CALL(myMock, theDelayedOutput())
.Times(1)
.Before(1.6sec)
.After(1.4sec);
Для уточнения Before
а также After
линии не поддерживаются. Это всего лишь пример того, что я бы предпочел в качестве простого синтаксиса.
Можно ли просто реализовать функцию «задержки» в окнах между выполнением входного вызова и перед проверкой EXPECT_CALL
?
Это часть пути — мне все равно придется запустить собственный таймер. Что-то вроде этого?
myMock.theInput();
windowSleep(1.4);
startTimer();
EXPECT_CALL(myMock, theDelayedOutput())
.Times(1)
endTimer();
ASSERT_TRUE(elapsedTime() <= 0.2);
Я уверен, что это решение будет работать для любого фреймворка без изменения фреймворка:
myMock.theInput();
startTimer();
EXPECT_CALL(myMock, theDelayedOutput());
endTimer();
ASSERT_TRUE(elapsedTime() >= 1.4);
ASSERT_TRUE(elapsedTime() <= 1.6);
Затем это можно обернуть в макрос:
#define EXPECT_CALL_DELAYED(theMock, expectCall, lowerBound, upperBound) {\
startTimer();\
EXPECT_CALL(theMock, expectCall);\
endTimer();\
ASSERT_TRUE(elapsedTime() >= lowerBound);\
ASSERT_TRUE(elapsedTime() <= upperBound);\
}
Итоговый тестовый код:
myMock.theInput();
EXPECT_CALL_DELAYED(myMock, theDelayedOutput(), 1.4, 1.6);
Кроме того, вы можете придерживаться принципа СУХОЙ и предварительно указать «окно» времени. Это позволяет вам проводить тестирование с указанием точного времени, но при этом не нужно будет повторяться, добавляя каждый раз 0,1-секундный буфер вверх и вниз.
EXPECT_CALL_DELAYED_SET_WINDOW(0.1);
myMock.theInput();
EXPECT_CALL_DELAYED(myMock, theDelayedOutput(), 1.5);
myMock.theSecondInput();
EXPECT_CALL_DELAYED(myMock, theSecondDelayedOutput(), 3.1);
Я не проверял ничего из этого, хотя. Я обновлю позже и приму, если это работает.
Так как вы пометили вопрос модульным тестированием: в модульном тестировании ваши тесты никогда не должны зависеть от физического времени. На это есть разные причины: во-первых, вы хотите, чтобы ваши тесты выполнялись как можно быстрее, поэтому вы не хотите задержек. Другая причина в том, что время в среде разработки (где выполняются ваши юнит-тесты) может полностью отличаться от целевой среды из-за разного оборудования, операционных систем, загрузки системы, …
То есть тесты, связанные с истечением физического времени, действительно имеют смысл, но они будут интеграционными тестами в целевой системе (или некоторой их имитацией). В модульном тестировании вы бы выбрали другой подход:
Вы бы высмеяли функции / методы, которые представляют ваши часы. Например, если ваша функция funcA устанавливает таймер через setTimer, предоставляя обратный вызов, который будет вызван по истечении времени:
В обоих случаях модульного тестирования вы не ждете, пока истечет физическое время.
Тем не менее, вы, безусловно, можете использовать те же инфраструктуры тестирования, которые используются для модульного тестирования, а также для интеграционного тестирования (даже если их имена, такие как JUnit, указывают на то, что они предназначены только для модульного тестирования). И, если интеграционное тестирование на самом деле является видом тестирования, к которому вы стремитесь, предложения Джеффа Лэмба определенно помогут.