I rely on equipment that may or may not respond. As a result, I often end up with timeouts. System time is a well-known source for fragile unit tests, so introducing controlled and stable time seems like a good idea for testing.
I wonder if there are any tools in std :: chrono that help with this. The alternative that I see is to write a wrapper around the system time and depend on this adapter.
Here is a minimal example of what a wrapper looks like.
#pragma once #include <memory> #include <chrono> #include <thread> #include <iostream> using std::chrono::system_clock; using std::chrono::milliseconds; using std::shared_ptr; using std::make_shared; class Wrapped_Clock { public: virtual system_clock::time_point Now() { return system_clock::now(); } virtual void Sleep(milliseconds ms) { std::this_thread::sleep_for(ms); } }; class Mock_Clock : public Wrapped_Clock { private: system_clock::time_point now; public: Mock_Clock() : now(system_clock::now()){} ~Mock_Clock() {} system_clock::time_point Now() { return now; } void Sleep(milliseconds ms) { } }; class CanTimeOut { private: shared_ptr<Wrapped_Clock> sclock; public: CanTimeOut(shared_ptr<Wrapped_Clock> sclock = make_shared<Wrapped_Clock>()) : sclock(sclock) {} ~CanTimeOut() {} milliseconds TimeoutAction(milliseconds maxtime) { using std::chrono::duration_cast; int x = 0; system_clock::time_point start = sclock->Now(); system_clock::time_point timeout = sclock->Now() + maxtime; while (timeout > sclock->Now() && x != 2000) { sclock->Sleep(milliseconds(1)); ++x; } milliseconds elapsed = duration_cast<milliseconds>(sclock->Now() - start); return elapsed; } }; #define EXPECT_GE(left, right, test) \ { if (!(left >= right)) { \ std::cout << #test << " " << "!(" << left << " >= " << right << ")" << std::endl; \ } } #define EXPECT_EQ(expected, actual, test) \ { if (!(expected == actual)) { \ std::cout << #test << " " << "!(" << expected << " == " << actual << ")" << std::endl; \ } } void TestWithSystemClock() { CanTimeOut cto; long long timeout = 1000; milliseconds actual = cto.TimeoutAction(milliseconds(timeout)); EXPECT_GE(actual.count(), timeout, TestWithSystemClock); } void TestWithMockClock() { CanTimeOut cto(make_shared<Mock_Clock>()); milliseconds actual = cto.TimeoutAction(milliseconds(1000)); EXPECT_EQ(0, actual.count(), TestWithMockClock); } int main() { TestWithSystemClock(); TestWithMockClock(); }
How much of this can be replaced with functionality from std :: chrone?
Change 1:
- "What exactly are you testing?" I control time as a test condition in order to change the behavior of calls to time-dependent methods. The test illustrates that it mocks time and controls behavior, how the concept works, and shows my understanding of this. The point of a minimal example is to show my understanding of mocking time so that it is easier to show the differences with the capabilities of
std:: . - "spend ~ 10 words saying tests should contrast." One Test always expires. There is no time in another test. The third test, which controls the accurate and non-zero passage of time, was not included.
- “Besides, a dream has nothing to do with a watch. It's not a chronograph.” I needed it to ensure that one test never goes in cycles more than a certain amount before timing, this mimics some actions that require time and time. On the other hand, I wanted to create a shortcut so that the second test did not waste time waiting. It would be nice not to make fun of the dream, but the test will take 2 seconds. I admit that Sleep is not a feature of the chronograph and therefore is misleading.
source share