3

Sorry for the bad title, I have no idea how to title this question. Please edit and make it better.

I am writing a test using the Qt test framework, and I'm trying to write some useful output to be used by the QVERIFY2() macro. All of the following statements have failed to compile with roughly the same error message:

QVERIFY2( spy.count() == 1, "Emitted signal pathChanged() was emitted " + spy.count() + " times instead of 1 time" );
QVERIFY2( spy.count() == 1, QString( "Emitted signal pathChanged() was emitted " ) + QString( spy.count() ) + QString( " times instead of 1 time" ) );
QVERIFY2( spy.count() == 1, "Emitted signal pathChanged() was emitted " + QString( spy.count() ) + " times instead of 1 time" );

The error message for the last attempt was:

PathTester.cxx: In member function ‘void PathTester::testReservePath()’:
PathTester.cxx:241:128: error: cannot convert ‘QString’ to ‘const char*’ for argument ‘3’ to ‘bool QTest::qVerify(bool, const char*, const char*, const char*, int)’
PathTester.cxx:241:243: error: cannot convert ‘QString’ to ‘const char*’ for argument ‘3’ to ‘bool QTest::qVerify(bool, const char*, const char*, const char*, int)’

What am I doing wrong? How can I write that correctly?

Freedom_Ben
  • 11,247
  • 10
  • 69
  • 89
  • It wants a const char* and not a QString... – Son-Huy Pham Jun 27 '13 at 22:07
  • The output that you pasted looks extremely fishy -- namely, the opening round bracket `FAIL! : PathTester::testPath() '(` <-- here. Is it really that way? Also, what does `expectedNum` contain at that point (dump it just before the verify), and why isn't it in the test itself? – peppe Jul 08 '13 at 16:44
  • @peppe You're right, it was fishy. That `(` was not there in the code (must have added it unintentionally??) Fortunately, when I went back to look at the original I realized that I was reading the output from a copy/pasted line that wasn't updated with `QString::number()` \*sigh\*. Looks like it was a hardware failure between the chair and the keyboard :-) It's one of those days... I removed the boneheadedness from the question. Thanks again for all your help – Freedom_Ben Jul 08 '13 at 17:07

2 Answers2

11

Use QVERIFY2(condition, qPrintable(...)) when using a QString.

The second argument must be a const char *. In all of your cases you're creating a QString instead -- which is indeed very convenient because it allows you to use + for concatenation, or QString::arg(), etc; you need a conversion to char *, which is not implicit, and that's what qPrintable() does.

To elaborate: qPrintable(string) is a shorthand for string.toLocal8Bit().constData(). Qt 5.4 will also introduce qUtf8Printable(string) which is the equivalent of string.toUtf8().constData().

Addendum: apart from the technicality of what to pass to QVERIFY2, why aren't you using QCOMPARE(spy.count(), 1)? In case of failure it will emit the expected value and the actual value.

peppe
  • 21,934
  • 4
  • 55
  • 70
1

I'd like to add my 5 cents. While you actually may use QCOMPARE in your specific case as @peppe suggested, sometimes you may need to provide a more detailed message. That the case for QVERIFY2. The best way for formatting message in this case that I know is exploitation of QString::arg() method. For example in you case you could write:

QVERIFY2 (
    spy.count() == 1, 
    qPrintable (
        QString ("Emitted signal pathChanged() was emitted %1 times instead of %2 time(s)")
        .arg (spy.count())
        .arg (1)));

This way you get a more readable code and may change both actual count and expected count expressions.

ChrisE
  • 3
  • 4