Details
-
Suggestion
-
Resolution: Unresolved
-
Not Evaluated
-
None
-
None
-
None
Description
Our code uses QTimers extensively - both repeating QTimers and singleshot QTimer.
Unfortunately this makes writing tests very sad, because the tests take a long time to run and can be flaky (when a typical timeout is eg 2 minutes this adds up quickly).
It would be nice if there was some way we could "fake" the passage of time for testing - eg an "enableDeterministicTime() + advanceTimeBy()" API? This would allow us to run tests with deterministic timings, and most tests would complete immediately rather than taking minutes.
Existing work arounds:
- we can mock QTimer and inject, which works, but requires us to maintain and document a custom QTimer like API, convert over older code, and it doesn't work for static methods like QTimer::singleShot (this is our current approach)
- we can write a QTimer wrapper and switch in another implementation when compiling test binaries, but this has similar issues to mocking + injection except that static methods can be implemented
- exposing the relevant callbacks as slots and calling them directly in the tests, which exposes implementation details and doesn't work with lambda arguments
- we can use some LD_LIBRARY_PRELOAD magic to fake the underlying calls, but this isn't portable and seems like it will break easily if Qt changes
Other people that might benefit from such a feature:
- https://forum.qt.io/topic/88268/are-there-any-techniques-to-fast-forward-time-for-testing-purposes-in-a-qt-application
- https://stackoverflow.com/questions/63055594/how-to-manually-mock-qtimer
- https://stackoverflow.com/questions/55064916/qt5-qtest-how-to-mock-the-clock-speed-qtimer-etc
- https://stackoverflow.com/questions/40401863/controlling-time-of-qtimer
- https://stackoverflow.com/questions/62811965/injecting-a-mock-of-a-qtimer