-
Notifications
You must be signed in to change notification settings - Fork 318
test: Use QSignalSpy instead of QEventLoop #335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,9 +20,9 @@ | |
#endif | ||
|
||
#include <QAction> | ||
#include <QEventLoop> | ||
#include <QLineEdit> | ||
#include <QScopedPointer> | ||
#include <QSignalSpy> | ||
#include <QTest> | ||
#include <QTextEdit> | ||
#include <QtGlobal> | ||
|
@@ -33,13 +33,14 @@ namespace { | |
//! Call getblockchaininfo RPC and check first field of JSON output. | ||
void TestRpcCommand(RPCConsole* console) | ||
{ | ||
QEventLoop loop; | ||
QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget"); | ||
QObject::connect(messagesWidget, &QTextEdit::textChanged, &loop, &QEventLoop::quit); | ||
QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit"); | ||
QSignalSpy mw_spy(messagesWidget, &QTextEdit::textChanged); | ||
QVERIFY(mw_spy.isValid()); | ||
QTest::keyClicks(lineEdit, "getblockchaininfo"); | ||
QTest::keyClick(lineEdit, Qt::Key_Return); | ||
loop.exec(); | ||
QVERIFY(mw_spy.wait(1000)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why 1000? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No specific reason, just an arbitrary number. Would you suggest leaving it as the default value of 5000 milliseconds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm ok if CI passes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. focal CI failure seems unrelated: https://cirrus-ci.com/task/5251590773800960?logs=ci#L3432 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't switching from exec to wait(1000) make the test non-deterministic? The previous There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Looking at the source code for the qsignalspy wait function, we can see the following line:
Going to the source for the enterLoopMSecs function, we can observe that
As I see it, if there is a downside, it is that this part of the test will always wait for 1000ms. So if the signals are received in 1ms, the loop will continue waiting for 999 more ms. At the same time, it is possible that the test fails because the signals weren't received within 1000ms because the CI is slow. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good if test isn't failing. Just if the test turns out to be unreliable, I'd recommend reverting. I see only downsides and no upsides to using signal spy in this instance. It makes the test more fragile, more verbose, and less straightforward, waiting indirectly though a hidden event loop in an inflexible and poorly documented test class, instead of just running the code we need to run directly in a deterministic way. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for taking the time to review! I think if this turns out to be unreliable on the part of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure why a "signal spy" would be more intuitive than an "event loop". The previous code is telling the event loop to quit when the textChanged signal happens. The new code is telling the signal spy to wait until the textChanged signal happens. I'd think both versions should be about as intuitive at the test behavior level. Only an event loop is a well known construct that I think you need to understand anyway to use Qt, while a signal spy is a specialized test class (with a hidden event loop inside) that makes you worry about timeouts and leaves you "going to the source for the enterLoopMSecs function" to find out how they work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see any benefit to the test counting its own signal emissions either. The goal of the test is to trigger an rpc, wait for the rpc, and check the rpc result. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I'm probably sounding too cranky about this. I definitely appreciate any work on these tests, and think this change is basically fine, but just wanted to point out some drawbacks I see and point to a resolution just in case there do turn out to be reliability problems. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
😀 no worries. Please always be as vocal as possible, we all just want to ensure good changes occur. There is one hidden bug case that the original code wouldn't detect. And another that this version does a (very slightly) better job of diagnosing. Scenario A: No Actual console response Now, let's say we introduce a bug where the console fails to present output to your command. The old version will pass on the Scenario B: Double console response Furthermore, let's say we introduce a bug where a |
||
QCOMPARE(mw_spy.count(), 2); | ||
QString output = messagesWidget->toPlainText(); | ||
UniValue value; | ||
value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString()); | ||
|
Uh oh!
There was an error while loading. Please reload this page.