Тайм-аут QTimer не запускается при юнит-тестировании - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь создать модульное тестирование для класса, который я создал с именем Counter.Такой класс должен уменьшать свое значение «count» каждые 0,1 секунды, поэтому я подключил метод в конструкторе классов.В оригинальной программе все работает нормально, но когда я пытаюсь запустить тестер модулей, кажется, что соединение не произошло или QTimer вообще не отправляет сигнал тайм-аута.

ссылка на gitHub: https://github.com/allocro/TimerLFdP/tree/master/testCounter

Counter::Counter(QLineEdit *editSec, QLineEdit *editMin, QObject *parent) : 
QObject(parent)
{
    timer= new QTimer(this);
    [...]
    connect(timer, &QTimer::timeout, this, &Counter::decCount);
}

РЕДАКТИРОВАТЬ: K, я постараюсь разместить здесь другую часть кода, как меня просят.

В предыдущем коде, вот конструкторкласса, который я хочу проверить, что decCount () не делает ничего, кроме этого:

void Counter::decCount(){
    if (count>0)
        count--;
    else
        timer->stop();

    int countsec = count % 600;
    int countmin = (count - countsec)/600;

    QString secOut = QString::number(countsec/10) + "." 
    +QString::number(countsec%10);

    emit showCountMin(countmin);
    emit showCountSec(secOut);
} 

Приведенные выше сигналы не имеют отношения к коду тестера, они использовались в полной программе.

Теперь, в tst_testCounter.cpp, который, насколько я понял, является версией тестового модуля классического main, и я получил

testCounter::testCounter() : QObject ()
{   int i;
    editSec= new QLineEdit();
    editMin= new QLineEdit();
    counter= new Counter(editSec, editMin);
    for(i=0; i<=10; i++){
        int randsec= rand() %60;
        int randmin= rand() %60;
        randsec=3;
        randmin=0; //To test the tester faster

        QString randsecString= QString::number(randsec);
        QString randminString= QString::number(randmin);


        editSec->setText(randsecString);
        editMin->setText(randminString);

        counter->set();//those are to input, they work fine, I checked
        std::cout << "Starting the Timer at " << (counter->count)/10 << 
        "sec" <<std::endl;
        counter->start(); //{timer->start();}

        while(counter->count>0){
            std::cout <<counter->count <<std::endl;
        }
        auto end= std::chrono::system_clock::now();
        counter->stop();

        auto check= std::chrono::duration_cast<std::chrono::seconds>(end - 
        start);
        int checkInt= check.count();

        if(checkInt==randsec+(randmin*60)){
            std::cout << "Timer matches" <<std::endl;
        }else{
        std::cout << "Timer doesnt match" <<std::endl;
        std::cout << "Sec counted: " << (counter->count)/10 <<std::endl;
        std::cout << "Sec passed: " << checkInt <<std::endl;
        break;
        }
    }
}

И, очевидно, .cpp заканчивается на

QTEST_MAIN(testCounter)

#include "tst_testcounter.moc"

1 Ответ

0 голосов
/ 21 сентября 2018

Первое, что вы должны иметь в виду, это то, что QTimer не является точным, поэтому проверка в порядке секунд вызовет проблемы, лучший тест проверяет, что разница во времени в мс меньше определенной величины.

С другой стороны, с инструкцией:

while (counter-> count> 0) {
    std::cout << counter-> count << std::endl;
}

Вы не позволяете циклу событий работать, и поэтому QTimer или сигналы могут работать.

Что вы должны использоватьis QCoreApplication::processEvents():

while(counter.count>0){
    QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
}

Также рекомендуется определять элементы теста в методах, и тест дается не в конструкторе, а в слотах.

Учитывая вышеизложенное и предоставляя другие улучшения, получается следующее:

counter.h

#ifndef COUNTER_H
#define COUNTER_H

#include <QObject>
class QTimer;
class QLineEdit;

class Counter : public QObject
{
    Q_OBJECT
public:
    explicit Counter(QLineEdit *setterSec, QLineEdit *setterMin, QObject *parent = nullptr);
    QTimer *timer;
    QLineEdit *setterSec;
    QLineEdit *setterMin;
    int count;
signals:
    void showCountSec(const QString &count);
    void showCountMin(int count);

public slots:
    void decCount();
    void start();
    void stop();
    void set();
};

#endif // COUNTER_H

counter.cpp

#include "counter.h"
#include <QTimer>
#include <QIntValidator>
#include <QLineEdit>

Counter::Counter(QLineEdit *editSec, QLineEdit *editMin, QObject *parent) :
    QObject(parent),
    timer(new QTimer(this)),
    setterSec(editSec),
    setterMin(editMin),
    count(0)
{
    setterSec->setValidator(new QIntValidator(0, 59, this));
    setterMin->setValidator(new QIntValidator(0, 59, this));
    connect(timer, &QTimer::timeout, this, &Counter::decCount);
}

void Counter::start(){
    timer->start(100);
}

void Counter::stop(){
    timer->stop();
}

void Counter::set(){
    timer->stop();
    count = setterSec->text().toInt()*10 + setterMin->text().toInt()*600;
    int countsec = count % 600;
    int countmin = (count - countsec)/600;

    QString secOut = QString::number(countsec/10) + "." +QString::number(countsec%10);

    emit showCountMin(countmin);
    emit showCountSec(secOut);
}

void Counter::decCount(){
    if (count > 0)
            count--;
    else
        timer->stop();

    int countsec = count % 600;
    int countmin = (count - countsec)/600;

    QString secOut = QString::number(countsec/10) + "." +QString::number(countsec%10);

    emit showCountMin(countmin);
    emit showCountSec(secOut);
}

tst_counter.h

#include <QtTest>
#include "counter.h"
#include <QLineEdit>
#include <iostream>
#include <cmath>
#include <QDebug>

// add necessary includes here

class tst_Counter : public QObject
{
    Q_OBJECT
public:
    tst_Counter();
    ~tst_Counter();

private slots:
    void initTestCD();
};

tst_Counter::tst_Counter() : QObject ()
{
}
tst_Counter::~tst_Counter()
{

}

void tst_Counter::initTestCD(){
    QLineEdit editSec;
    QLineEdit editMin;
    Counter counter(&editSec, &editMin);
    const int epsilon = 50; // ms

    for(int i=0; i<=10; i++){
        int randsec= rand() %60;
        int randmin= rand() %60;
        randsec =3;
        randmin =0; //To test the tester faster

        QString randsecString= QString::number(randsec);
        QString randminString= QString::number(randmin);


        editSec.setText(randsecString);
        editMin.setText(randminString);

        counter.set();//those are to input, they work fine, I checked
        qDebug() << "Starting the Timer at " << (counter.count)/10;

        auto start= std::chrono::system_clock::now();
        counter.start(); //{timer->start();}
        while(counter.count>0){
            QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
        }
        auto end= std::chrono::system_clock::now();
        counter.stop();
        auto check_ms= std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        int checkInt = check_ms.count();
        int delta_s = randsec + randmin*60;
        int delta = std::abs(checkInt - delta_s);
        QVERIFY(delta < epsilon);

        qDebug() << "Sec counted: " << counter.count/10;
        qDebug() << "msec passed: " << checkInt;
    }
}

QTEST_MAIN(tst_Counter)

#include "tst_counter.moc"

вывод:

********* Start testing of tst_Counter *********
Config: Using QtTest library 5.11.2, Qt 5.11.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 8.2.1 20180831)
PASS   : tst_Counter::initTestCase()
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  3033
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  3000
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  3000
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
QDEBUG : tst_Counter::initTestCD() Starting the Timer at  3
QDEBUG : tst_Counter::initTestCD() Sec counted:  0
QDEBUG : tst_Counter::initTestCD() msec passed:  2999
PASS   : tst_Counter::initTestCD()
PASS   : tst_Counter::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 33078ms
********* Finished testing of tst_Counter *********

В следующей ссылке вы можете найти полный пример.

...