PDA

View Full Version : QTestLib. A simple example. A list of the FAILS.



8Observer8
4th October 2013, 08:11
Hi,

I expect to see a list of the FAILS (8 FAILS). But I see only two:

Output:


********* Start testing of Test_Complex *********
Config: Using QTest library 4.8.5, Qt 4.8.5
PASS : Test_Complex::initTestCase()
FAIL! : Test_Complex::setIm() Compared doubles are not the same (fuzzy compare)

Actual (input): 25.5
Expected (complex.getIm()): 0
../TestLib_Complex/test.cpp(19) : failure location
FAIL! : Test_Complex::setRe() Compared doubles are not the same (fuzzy compare)

Actual (input): 25.5
Expected (complex.getRe()): 0
../TestLib_Complex/test.cpp(43) : failure location
PASS : Test_Complex::cleanupTestCase()
Totals: 2 passed, 2 failed, 0 skipped
********* Finished testing of Test_Complex *********
Press <RETURN> to close this window...

This is my code:

TestLib_Complex.pro


SOURCES += \
test.cpp

HEADERS += \
complex.h

CONFIG += qtestlib


complex.h


#ifndef COMPLEX_H
#define COMPLEX_H

class Complex {
public:
Complex(double i = 0, double r = 0)
:m_im(i), m_re(r){}

void setIm(double i) {
//m_im = i; // for test
}
void setRe(double r) {
//m_re = r; // for test
}
double getIm() {
return m_im;
}
double getRe() {
return m_re;
}

private:
double m_im;
double m_re;
};

#endif // COMPLEX_H


test.cpp


#include <QtTest>
#include "complex.h"
#include <QDebug>

class Test_Complex : public QObject {
Q_OBJECT
private slots:
void setIm();
void setRe();
};

// ----------------------------------------------------------------------
void Test_Complex::setIm()
{
Complex complex;

double input = 25.5;
complex.setIm(input);
QCOMPARE(input, complex.getIm());

input = -5.7;
complex.setIm(input);
qDebug() << "input = " << input;
qDebug() << "complex.getIm() = " << complex.getIm();
QCOMPARE(input, complex.getIm());

input = 0;
complex.setIm(input);
QCOMPARE(input, complex.getIm());

input = 5;
complex.setIm(input);
QCOMPARE(input, complex.getIm());
}

// ----------------------------------------------------------------------
void Test_Complex::setRe()
{
Complex complex;

double input = 25.5;
complex.setRe(input);
QCOMPARE(input, complex.getRe());

input = -5.7;
complex.setRe(input);
QCOMPARE(input, complex.getRe());

input = 0;
complex.setRe(input);
QCOMPARE(input, complex.getRe());

input = 5;
complex.setRe(input);
QCOMPARE(input, complex.getRe());
}

QTEST_MAIN(Test_Complex)
#include "test.moc"


Thank you!

nix
4th October 2013, 08:22
According to the documentation, if a QCOMPARE fails the test is aborded. So you have two test fonctions, it gives you two fails.

anda_skoa
4th October 2013, 08:50
The reason is that you need to be able to check assumption before continuing to test things that are based on that assumption.

Consider a test like this


QStringList result = someTestObject->someFunction();
QCOMPARE(result.count(), 2);
QCOMPARE(result[0], "some expected string");
QCOMPARE(result[1], "some other expected string");


If the first QCOMPARE would not abort the test, the second or third one would lead to an assert() in QList, crashing the test program.

Cheers,
_

8Observer8
4th October 2013, 13:11
Thank you, guys! I understand.

Added after 24 minutes:

Please, say me. Is this correct code for testing of my class? I implemented testing for 'get' and 'set' methods.

I took qFuzzyCompare() function from here: http://www.qtcentre.org/threads/52904-QtTest-How-to-compare-double-numbers?highlight=

I duplicate my code in my main project and in my TestLib_Comlex project. Must I copy/past my class (Complex) to main project all time?

Sorry for my English.

This is all my testLib project:

TestLib_Comlex.pro


SOURCES += \
test.cpp

HEADERS += \
complex.h

CONFIG += qtestlib


complex.h


#ifndef COMPLEX_H
#define COMPLEX_H

class Complex {
public:
Complex(double i = 0, double r = 0)
:m_im(i), m_re(r){}

void setIm(double i) {
m_im = i;
}
void setRe(double r) {
m_re = r;
}
double getIm() {
return m_im;
}
double getRe() {
return m_re;
}

private:
double m_im;
double m_re;
};

#endif // COMPLEX_H


test.cpp


#include <QtTest>
#include "complex.h"
#include <QDebug>

class Test_Complex : public QObject {
Q_OBJECT
private slots:
void setIm();
void setRe();

static inline bool qFuzzyCompare(double p1, double p2, double delta)
{
return (qAbs(p1 - p2) <= delta * qMin(qAbs(p1), qAbs(p2)));
}
};

// ----------------------------------------------------------------------
void Test_Complex::setIm()
{
Complex complex;

double input = 25.5123;
complex.setIm(input);
double expeted = complex.getIm();
double delta = 0.0001;
QString message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());

input = -5.7;
complex.setIm(input);
expeted = complex.getIm();
message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());

input = 0;
complex.setIm(input);
expeted = complex.getIm();
message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());

input = 5;
complex.setIm(input);
expeted = complex.getIm();
message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());
}

// ----------------------------------------------------------------------
void Test_Complex::setRe()
{
Complex complex;

double input = 125.5;
complex.setRe(input);
double expeted = complex.getRe();
double delta = 0.0001;
QString message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());

input = -15.7;
complex.setRe(input);
expeted = complex.getRe();
message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());

input = 10;
complex.setRe(input);
expeted = complex.getRe();
message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());

input = 15;
complex.setRe(input);
expeted = complex.getRe();
message = QString("input = %1; expeted = %2; delta = %3").arg(input).arg(expeted).arg(delta);
QVERIFY2(qFuzzyCompare(input, expeted, delta), message.toAscii());
}

QTEST_MAIN(Test_Complex)
#include "test.moc"

8Observer8
4th October 2013, 20:25
Hi,

I read about an another way of testing via addColumn(), newRow() and QFETCH. I like this way, but...

I cannot understand this errors:



********* Start testing of Test_Complex *********
Config: Using QTest library 4.8.5, Qt 4.8.5
PASS : Test_Complex::initTestCase()
QDEBUG : Test_Complex::setIm() expected data of type 'double', got 'int' for ele
ment 0 of data with tag 'setIm_test3'
QFATAL : Test_Complex::setIm() ASSERT: "false" in file qtestdata.cpp, line 94
FAIL! : Test_Complex::setIm() Received a fatal error.
Unknown file(0) : failure location
Totals: 1 passed, 1 failed, 0 skipped
********* Finished testing of Test_Complex *********

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Press <RETURN> to close this window...


TestLib_Comlex_table.pro


HEADERS += \
complex.h

SOURCES += \
test.cpp

CONFIG += qtestlib


complex.h


#ifndef COMPLEX_H
#define COMPLEX_H

class Complex {
public:
Complex(double i = 0, double r = 0)
:m_im(i), m_re(r){}

void setIm(double i) {
m_im = i;
}
void setRe(double r) {
m_re = r;
}
double getIm() {
return m_im;
}
double getRe() {
return m_re;
}

Complex operator+(Complex c) {
Complex sum;
sum.m_im = m_im + c.m_im;
sum.m_re = m_re + c.m_re;
return sum;
}

private:
double m_im;
double m_re;
};

#endif // COMPLEX_H


test.cpp


#include <QtTest>
#include "complex.h"

// ================================================== ====================
class Test_Complex : public QObject {
Q_OBJECT
private slots:
void setIm_data();
void setRe_data();

void setIm();
void setRe();
};

// ----------------------------------------------------------------------
void Test_Complex::setIm_data()
{
QTest::addColumn<double>("arg1");
QTest::addColumn<double>("result");

QTest::newRow("setIm_test1") << 0.0 << 0.0;
QTest::newRow("setIm_test2") << -12.5 << -12.5;
QTest::newRow("setIm_test3") << 2007 << 2007;
QTest::newRow("setIm_test4") << 5.1 << 5.1;
}

// ----------------------------------------------------------------------
void Test_Complex::setRe_data()
{
QTest::addColumn<double>("arg1");
QTest::addColumn<double>("result");

QTest::newRow("setRe_test1") << 0.0 << 0.0;
QTest::newRow("setRe_test2") << -12.5 << -12.5;
QTest::newRow("setRe_test3") << 2007 << 2007;
QTest::newRow("setRe_test4") << 5.1 << 5.1;
}

// ----------------------------------------------------------------------
void Test_Complex::setIm()
{
Complex complex;
QFETCH(double, arg1);
QFETCH(double, result);

complex.setIm(arg1);

QCOMPARE(complex.getIm(), result);
}

// ----------------------------------------------------------------------
void Test_Complex::setRe()
{
Complex complex;
QFETCH(double, arg1);
QFETCH(double, result);

complex.setRe(arg1);

QCOMPARE(complex.getRe(), result);
}

QTEST_MAIN(Test_Complex)
#include "test.moc"

nix
5th October 2013, 08:41
Use the rigth type for data in setIm_test3 to double instead of int ( 2007 become 2007.0 )

8Observer8
5th October 2013, 09:07
Yes, it works now! Thank you very much!