Reputation: 4214
QCOMPARE(
std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::infinity());
fails with:
Compared doubles are not the same (fuzzy compare)
Actual (std::numeric_limits<double>::infinity()): inf
Expected (std::numeric_limits<double>::infinity()): inf
Loc: [...]
Why does this fail? Is there a good work-around (other than using QVERIFY
instead)?
UPDATE:
I mean a work-around from the perspective of a test-writer. It is desirable to provide a proper diagnostic with the actual value which is not infinity. Instead of
QCOMPARE(val, std::numeric_limits<double>::infinity());
one could
QVERIFY(val == std::numeric_limits<double>::infinity()))
but the value of val
is not shown in the generated diagnostic message if the check fails. Looks like a major oversight from developers.
So do I have to roll-out my own macro with exact comparison similar to QCOMPARE
? Any recommendations here?
Also, it is clear that qFuzzyCompare
does not support some corner-cases. But I hoped for a more in-depth explanation of why this is the case.
Upvotes: 0
Views: 3525
Reputation: 428
Based on the approach by @thomas-klier, the following macro works for me:
#define COMPARE_DBL(actual, expected, epsilon) \
do {\
if (!QTest::compare_helper( ((qAbs(actual - expected) <= epsilon) || (actual == expected)), \
QString{"Compared values are not the same in respect to epsilon %1"} \
.arg(epsilon).toLocal8Bit().constData(), \
QTest::toString(actual), \
QTest::toString(expected), \
#actual, #expected, __FILE__, __LINE__)) \
return;\
} while (false)
Upvotes: 1
Reputation: 469
As there is still no working example, I post my own macro here:
#include <qtestcase.h>
#define COMPARE_DBL(actual, expected, epsilon) \
do {\
if (!QTest::compare_helper((qAbs(actual - expected) <= epsilon), \
QString{"Compared values are not the same in respect to epsilon %1"} \
.arg(epsilon).toLocal8Bit().constData(), \
QTest::toString(actual), \
QTest::toString(expected), \
#actual, #expected, __FILE__, __LINE__)) \
return;\
} while (false)
It prints out an error message formatted by Qt and correctly interrupts the test case.
Upvotes: 3
Reputation: 4214
I ended up writing a custom marco. It mimics QCOMPARE
output and does not stick out.
Here it is (feel free to re-use):
inline void isEqualsExactly(
const double actual,
const double expected,
const std::string& actualName,
const std::string& expectedName)
{
if(expected == actual)
return;
std::stringstream warn;
const size_t w = std::max(actualName.length(), expectedName.length());
warn << "Compared values are not the same" << std::endl;
warn << " Actual " << std::setw(w) << std::setfill(' ') << actualName;
warn << ": " << std::to_string(actual) << std::endl;
warn << " Expected " << std::setw(w) << std::setfill(' ') << expectedName;
warn << ": " << std::to_string(expected);
QFAIL(warn.str().c_str());
}
#define QCOMPARE_EXACT(actual, expected) \
isEqualsExactly(actual, expected, #actual, #expected);
Usage:
const double val = 0;
const double infinity = std::numeric_limits<double>::infinity();
QCOMPARE_EXACT(val, infinity);
Output:
FAIL! : TestName Compared values are not the same
Actual val: 0.000000
Expected infinity: inf
Loc: [link to location in file]
P.S. I agree, this should be a feature request. The situation is ridiculous. If I will make one, I will update the post.
Upvotes: 0
Reputation: 12821
QCOMPARE in the case of comparing floats and doubles, qFuzzyCompare() is used. (http://doc.qt.io/qt-5/qtest.html#QCOMPARE)
Based on (http://doc.qt.io/qt-5/qtglobal.html#qFuzzyCompare), Qt documentation it self says that comparing infinity will not work. - "Note that comparing values where either p1 or p2 is 0.0 will not work, nor does comparing values where one of the values is NaN or infinity".
My guess, why infinity can not be compared is, there is no specific value for infinity,I mean "infinity-1" is also infinity. Then obviously comparison is a question here.
Workaround:
If you want to compare infinity, Then use below function and compare the return Boolean values.
bool qIsInf(double d)
http://doc.qt.io/qt-5/qtglobal.html#qIsInf
Upvotes: 3