0

Can I get QTest to use a single data-driving set more than once?


We using Qt's QTest framework for the low-level tests in a project, and using data-driven style where it makes sense.

I've come to a point where I want to do several distinct sets of tests on a single set of test data. The obvious design is

void testcalss::teststuff_data()
{
    QTest::addColumn<int>("number");
    QTest::addColumn<double>("size");

    QTest::newRow("first") << 1 << 3.14;
    QTest::newRow("second") << 42 << 2.718;
}

void testclass::teststuff()
{
    QFETCH(int, number);
    QFETCH(double, value);

    // Test one thing about this stuff
    QCOMPARE( f(number), value );      // <=== If it fails here ...

    // test some other thing
    QCOMPARE( g(number), h(value));    // <=== ... it doesn't even try this
}

More or less right out of the documentation, right?

But a small annoyance is the way it shortcuts subsequent tests if an early one fails (notes in the comments). Sometimes this is a desired behavior and sometimes not, but just now I want it to try those second test even if the first one fails.

A possible alternate implementation scheme is

void testcalss::teststuff_data()
{
    QTest::addColumn<int>("number");
    QTest::addColumn<double>("size");

    QTest::newRow("first") << 1 << 3.14;
    QTest::newRow("second") << 42 << 2.718;
}

void testclass::teststuff()
{
    QFETCH(int, number);
    QFETCH(double, value);

    QCOMPARE( f(number), value );      
}

void testclass::teststuff2()
{
    QFETCH(int, number);              // <=== No data!
    QFETCH(double, value);

    QCOMPARE( g(number), h(value));    

}

but, of course, the input from teststuff_data() has already been consumed by the time teststuff2 starts.

Community
  • 1
  • 1
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234

1 Answers1

0

This trick is to re-invoke the previous code in a context that Qt recognizes as setting up some data. A new _data method that just calls the old one does not require any code duplication.

void testcalss::teststuff_data()
{
    QTest::addColumn<int>("number");
    QTest::addColumn<double>("size");

    QTest::newRow("first") << 1 << 3.14;
    QTest::newRow("second") << 42 << 2.718;
}

void testclass::teststuff()
{
    QFETCH(int, number);
    QFETCH(double, value);
    QCOMPARE( f(number), value );
}

void testclass::teststuff2_data()    // <=== define a _data method that ...
{
    teststuff_data();                // <=== ... re-runs the previous set-up
}

void testclass::teststuff2()
{
    QFETCH(int, number);
    QFETCH(double, value);

    QCOMPARE( g(number), h(value));
}

As usual the test framework is sensitive to the order of method declaration so the header should look like

class testclass: public QObject
{
   Q_OBJECT

// c'tor and what not ...

private slots:
   void teststuff_data();
   void teststuff;

   void teststuff2_data();
   void teststuff2;
}
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234