Re: Googletest value printer for QString

2,506 views
Skip to first unread message

Ray Scheufler

unread,
Aug 9, 2012, 11:00:12 PM8/9/12
to googletes...@googlegroups.com
I did some more playing around and I got the following to work:

#include <gtest/gtest.h>
#include <QString>
#include <iostream>
#include <QDebug>

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

::std::ostream& operator<<(::std::ostream& os, const QString& bar)
{
    return os << "QString(" << bar.toStdString() << ")";
}

::std::ostream& operator<<(::std::ostream& os, const QChar& c)
{
    return os << c.toAscii();
}

TEST(One, Two)
{
    QString first("hello");
    QString second("World");

    EXPECT_EQ(first,second);

    qDebug() << first;
    std::cout << first << std::endl;

    for(QString::Iterator it = first.begin(); it != first.end(); it++)
    {
        std::cout << *it;
    }
    std::cout << std::endl;
}

It doesn't produce perfect output but it is at least has close:

[==========] Running 1 test from 1 test case.

[----------] Global test environment set-up.

[----------] 1 test from One

[ RUN ] One.Two

../untitled/main.cpp:27: Failure

Value of: second

Actual: { W, o, r, l, d }

Expected: first

Which is: { h, e, l, l, o }

QString(hello)

hello

[ FAILED ] One.Two (1 ms)

[----------] 1 test from One (1 ms total)


[----------] Global test environment tear-down

[==========] 1 test from 1 test case ran. (1 ms total)

[ PASSED ] 0 tests.

[ FAILED ] 1 test, listed below:

[ FAILED ] One.Two


1 FAILED TEST

"hello"


Ray Scheufler

On Thursday, August 9, 2012 9:08:30 PM UTC-5, Ray Scheufler wrote:
I'm also having this problem.  It appears that google test thinks that the QString is a collection and tries to print it as such.  I didn't have any luck trying to print the characters by themselves.

Ray Scheufler

On Monday, July 16, 2012 8:14:49 AM UTC-5, Ole wrote:
Hey folks,

I hope this is the right place to ask.

We are using Googletest 1.6 for our unit testing and are very happy with it. One slight inconvenience, however, is that a large part of our code uses QString instead of std::string, and printing QString when assertions fail does not work out of the box. Now I have read in the manual that you have already forseen this and similar cases, and build in a mechanism that allows people to define a PrintTo function for their classes to teach gtest how to print them. I have tried it with an example class as described in the AdvancedGuide for GTest 1.6, and it works fine. Now I am trying to do the same for QString, but cannot get it to work. The PrintTo method I have declared is just not called. There is a little comment in the docs saying that it needs to be defined in the same namespace as the class I want to print. However, we are not using namespaces with Qt (I can declare QString without using declaration/directive and without indicating the namespace). Does this work for anyone else? Does anyone have an idea why it would not work for QString? For the sake of completeness, see the code below:

#include <gtest/gtest.h>
#include <QtCore/QString>
#include <QtCore/QDebug>

void PrintTo(const QString& bar, ::std::ostream* os) {
  qDebug() <<  "PrintTo is called"; // is never called
  *os << bar.toStdString();
}

TEST(TestTest, testQString) {
  QString s1("bla");
  QString s2("blub");
  EXPECT_EQ(s1, s2); // fails as expected, but prints something about to 2-byte objects being unequal, and not, as expected, bla != blub
}


We currently work around this problem calling .toStdString() on both operands of the assertion, but that clutters the code quite a bit and is also somewhat annoying considering there is a mechanism that is supposed to avoid just that.

Thank you for your help,

Ole

Stefan

unread,
Nov 3, 2014, 1:48:47 AM11/3/14
to googletes...@googlegroups.com
Hi everyone,

I tried Jeffrey's approach, but it does not seem to work for me. I still get the non-readable output

[ RUN      ] One.Two
../UnitTests/tests/printtotest.cpp:21: Failure
Value of: second
  Actual: { 2-byte object <57-00>, 2-byte object <6F-00>, 2-byte object <72-00>, 2-byte object <6C-00>, 2-byte object <64-00> }
Expected: first
Which is: { 2-byte object <68-00>, 2-byte object <65-00>, 2-byte object <6C-00>, 2-byte object <6C-00>, 2-byte object <6F-00> }
[  FAILED  ] One.Two (0 ms)

Any idea why the PrintTo function might not work for QString? I use Qt 5.3 and CLang Compiler on MAC.



On Tuesday, May 7, 2013 7:39:43 PM UTC+2, Jeffrey Grant wrote:
I too stumbled upon this post in a google search. I might proffer a solution that I think is an improvement on Ray Scheufler's and J Hallam's. 

#include <gtest/gtest.h>
#include <QtCore/QString>
#include <iostream>
#include <QtCore/QDebug>

void PrintTo(const QString& str, ::std::ostream* os)
{
    *os << "QString(" << str.toStdString() << ")";
}

void PrintTo(const QChar& chr, ::std::ostream* os)
{
    *os << "QChar(" << chr.toAscii() << ")";
}

TEST(One, Two)
{
    QString first("hello");
    QString second("World");

    EXPECT_EQ(first,second);
}

Compare the output of Ray's version using the left shift operator (somewhat updated to match the above formatting):

qt.cpp:33: Failure
Value of: second
  Actual: { QChar(W), QChar(o), QChar(r), QChar(l), QChar(d) }
Expected: first
Which is: { QChar(h), QChar(e), QChar(l), QChar(l), QChar(o) }

to the output using PrintTo:

qt.cpp:33: Failure
Value of: second
  Actual: QString(World)
Expected: first
Which is: QString(hello)

The use of the PrintTo interface within GTest I think gets closer to the expected output.  From the GTest documentation, if both the PrintTo function and left shift operator are present, the PrintTo function is preferred. I'm not sure why, but it doesn't seem that the left shift operator for the QString is actually chosen (it appears to be treating the QString as an STL-container class and using the iterator interface instead), while using PrintTo results the desired function being called. J Hallam's solution does print the actual string value through the use of toStdString, but also leaves the native printing of the QString before streaming custom error message. Using PrintTo prints only the desired string value.  The pattern is repeatable for most of the Qt types. I hope this helps.

Jeff

On Sunday, April 14, 2013 9:24:15 PM UTC-4, J Hallam wrote:
This is an old post but its still prominent on google searches.

I solved this more elegantly (I think) than Mr Scheufler by making a macro:

#define ASSERT_EQ_QSTRING(a, b) ASSERT_EQ(a, b) << "`" << a.toStdString() << "` != `" << b.toStdString() << "`"

This has the plus side of comparing the strings in their normal form (as opposed to std::string) under the ASSERT_EQ() macro but degrading to .toStdString() if the test case fails.

Samuel Benzaquen

unread,
Nov 4, 2014, 12:54:13 PM11/4/14
to Stefan, Google C++ Testing Framework
On Mon, Nov 3, 2014 at 1:48 AM, Stefan <stefan.h...@googlemail.com> wrote:
Hi everyone,

I tried Jeffrey's approach, but it does not seem to work for me. I still get the non-readable output

[ RUN      ] One.Two
../UnitTests/tests/printtotest.cpp:21: Failure
Value of: second
  Actual: { 2-byte object <57-00>, 2-byte object <6F-00>, 2-byte object <72-00>, 2-byte object <6C-00>, 2-byte object <64-00> }
Expected: first
Which is: { 2-byte object <68-00>, 2-byte object <65-00>, 2-byte object <6C-00>, 2-byte object <6C-00>, 2-byte object <6F-00> }
[  FAILED  ] One.Two (0 ms)

Any idea why the PrintTo function might not work for QString? I use Qt 5.3 and CLang Compiler on MAC.

Can you give a little more context?
Which version of gTest is being used?
Can you show a little snippet of code that reproduces your problem? It is exactly Jeffrey's code?
Did you check whether PrintTo() is defined in the same namespace as QString?
Does it work if you define operator<<() instead of PrintTo() ?

_Sam
 

--

---
You received this message because you are subscribed to the Google Groups "Google C++ Testing Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to googletestframe...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stefan

unread,
Nov 7, 2014, 1:34:55 AM11/7/14
to googletes...@googlegroups.com, stefan.h...@googlemail.com
Hi Sam,

I use gtest 1.7.0, Qt 5.3.0 and clang on MacOS.

I copied Jeffrey's code exactly and it didn't work. I also tried adding the << operator, which did not help either.
It turns out that Qt by default uses the global namespace. It will only use a dedicated namespace if this is switched on during compilation, which was not the case for me.

I'm a little bit stuck now. Do you have any ideas?

Thanks!
Stefan
Reply all
Reply to author
Forward
0 new messages