Skip to content

August 2019

Comparing Two Floating-Point Numbers

The mathematician Leopold Kronecker is believed to have said:

God made the integers, all else is the work of man.

And Kronecker didn’t even know the floating-point numbers “made” for computers. Comparing two numbers of type float or double in C++ and related languages is a source for regular errors. When are the if-conditions in the following code snippet true?

float actual = calculate(10.0f, 0.2f, 45); // 10 - 0.2 * 45 = 1
if (actual == 1.0f) {
    // is this ever executed?
}
if (actual - 1.0f == 0.0f) {
    // is this ever executed?
}

The function calculate produces the result 10 – 0.2 * 45 = 10 – 9 = 1 – at least for human beings. So, both conditions should be true. However, they are both false.

If we turn on the warning -Wfloat-equal, the compiler will warn us that comparing floating point with == or != is unsafe. The compiler tells us what is wrong, but not how to fix it. I’ll explain why the above “solution” is wrong, why another obvious “solution” is nearly as bad, and why even the Qt function qFuzzyCompare can still be improved.

Read More »Comparing Two Floating-Point Numbers

QTest: Data-Driven Unit Tests Are Hard To Understand

Today, I looked at the data-driven unit tests I had written nearly four weeks ago. It took me a couple of minutes to understand the tests again. Understanding my own tests should have been much easier.

Data-driven unit tests in QTest have a fundamental problem. The data goes in one function, say testWriteFrame_data, and the test case working on the data goes in another function, say testWriteFrame. I must go back and forth to understand the test case. While going back and forth, I typically forget one piece of information. So, I must do another round trip.

So, I sat down and converted each row of the table created by testWriteFrame_data into a test function of its own. The resulting test cases are much easier to understand. They have about the same code size as the original solution. But see for yourself.

Read More »QTest: Data-Driven Unit Tests Are Hard To Understand

QCOMPARE with Custom Qt Types

When you write unit tests, you will have to compare the actual value and the expected value. A simplified example with QStrings would look like this.

void MyTest::testQCompare() {
    auto actualStr = QString{"abba"};
    auto expectedStr = QString{"juhu"};
    QCOMPARE(actualStr, expectedStr);
}

When you run this unit test, the QTest framework will print the actual value "abba" and the expected value "juhu". This is often enough to know what went wrong.

FAIL!  : MyTest::testQCompare() Compared values are not the same
   Actual   (actualStr)  : "abba"
   Expected (expectedStr): "juhu"

If two values of a custom type differ, the QTest framework will only print the first line: Compared values are not the same. This is not very helpful. How can you make QCOMPARE print the actual and expected for custom types as well?

Read More »QCOMPARE with Custom Qt Types