문제

나는 그냥 시작하는 새로운 프로젝트를 필요로 하는 일부 크로스-플랫폼을 구하고 우리가 선택 또는 데이터베이스를 필요로 GUI-framework.

우리는 필요한 단위 테스트 프레임워크에,너무입니다.약 년 전까지 우리가 사용하는에서 개발한 장치-테스트 framework for C++-프로젝트,하지만 우리는 이제로 전환하기를 사용하여 Google 테스트에 대한 새로운 프로젝트입니다.

누군가가 어떤 체험과 함께 사용하여 Google 에 대한 테스트 Qt-응용 프로그램은 무엇입니까?은 QtTest/QTestLib 더 나은 대안이?

나는 여전히 확실하지 않은 우리가 얼마나 사용하려는 Qt 에서 비 GUI 프로젝트의 부분-우리는 아마 선호를 사용하여 STL/부스트에서 핵심 코드 작은 인터페이스를 Qt-based GUI.

편집: 그것은 다음과 같은 기울고 있으로 QtTest.누군가 있다는 어떤 경험을 통합함으로 지속적인 통합 서버입니까?또한,그것은 내 것을 가을 처리하는 별도의 응용 프로그램를 위한 각각의 새로운 테스트 사례 원인의 많은 마찰.어떤 좋은 방법으로 해결하는가?는 Qt 창조주 좋은 방법의 취급 같은 테스트를 경우 또는 당신은 필요한 프로젝트별 테스트 사례?

도움이 되었습니까?

해결책

내가 알지 못하는 QTestLib 는 것보다 더 나은 것이 하나의 프레임워크에 대한 다른에서 이러한 일반 약관습니다.한 가지가 있는지,그리고 제공하는 좋은 방법이 테스트 Qt 기반 응용 프로그램입니다.

할 수 있는 통합 QTest 으로 새로운 구글은 테스트 기반의 설정입니다.나는 그것을 시도하지 않은,그러나 방법에 따라 QTestLib 도록 구성되어,그것은 보인 그것이 너무 복잡합니다.

테스트를 서면으로 순수한 QTestLib 있는 xml 옵션을 사용할 수 있는,함께 일부 XSLT 변환로 변환하여 필요한 형식을 위해 지속적인 통합 서버입니다.그러나,많은 것에 따라 달라집 CI 서버에 당신과 함께 할 것입니다.내가 상상하는 것에 동일하게 적용됩 GTest.

단일 테스트 응용 프로그램별 테스트 사례 적이 많이 발생의 마찰 저지만,그에 따라 달라지는 시스템을 구축하는 것은 괜찮은 직업을 관리하는 건축 및 실행 시험의 경우입니다.

난 아무것도의에서는 Qt 자는 별도의 프로젝트별 테스트 케이스 그러나 그것은 변경할 수 있기 때문에 마지막 시간에서 나는 보았다 Qt 창조자입니다.

또한 제안을 고집다.에서 머물고 STL.를 사용하여 여에 걸쳐 만들 것을 다루는 GUI 를 조금이 필요 Qt 데이터 유형을 쉽습니다.지 않을 것에 대해 걱정 하나에서 변환하는 데이터의 유형이 다른 경우.

다른 팁

별도의 테스트 응용 프로그램을 만들 필요가 없습니다. 독립적 인 main () 함수에서 qexec을 사용하기 만하면 다음과 유사합니다.

int main(int argc, char *argv[])
{
    TestClass1 test1;
    QTest::qExec(&test1, argc, argv);

    TestClass2 test2;
    QTest::qExec(&test2, argc, argv);

    // ...

    return 0;
}

이렇게하면 각 클래스의 모든 테스트 방법이 한 배치로 실행됩니다.

TestClass .h 파일은 다음과 같이 보입니다.

class TestClass1 : public QObject
{
Q_OBJECT

private slots:
    void testMethod1();
    // ...
}

불행히도이 설정은 많은 사람들에게 매우 유용한 것처럼 보이지만 QT 문서에서 실제로 잘 설명되어 있지 않습니다.

Joe의 대답에 추가됩니다.

다음은 이벤트 루프 (예 : 대기열 신호 슬롯 연결 및 데이터베이스를 테스트하는 데 필요한) 및 "실행"QTest 호환 클래스를 포함하는 유틸리티 클래스가 포함 된 작은 헤더 (TestRunner.h)입니다.

#ifndef TESTRUNNER_H
#define TESTRUNNER_H

#include <QList>
#include <QTimer>
#include <QCoreApplication>
#include <QtTest>

class TestRunner: public QObject
{
    Q_OBJECT

public:
    TestRunner()
        : m_overallResult(0)
    {}

    void addTest(QObject * test) {
        test->setParent(this);
        m_tests.append(test);
    }

    bool runTests() {
        int argc =0;
        char * argv[] = {0};
        QCoreApplication app(argc, argv);
        QTimer::singleShot(0, this, SLOT(run()) );
        app.exec();

        return m_overallResult == 0;
    }
private slots:
    void run() {
        doRunTests();
        QCoreApplication::instance()->quit();
    }
private:
    void doRunTests() {
        foreach (QObject * test, m_tests) {
            m_overallResult|= QTest::qExec(test);
        }
    }

    QList<QObject *> m_tests;
    int m_overallResult;
};

#endif // TESTRUNNER_H

다음과 같이 사용하십시오.

#include "testrunner.h"
#include "..." // header for your QTest compatible class here

#include <QDebug>

int main() {
    TestRunner testRunner;
    testRunner.addTest(new ...()); //your QTest compatible class here

    qDebug() << "Overall result: " << (testRunner.runTests()?"PASS":"FAIL");

    return 0;
}

나는 앱에 QTTest를 사용하기 시작했고 매우 빨리 제한을 시작하기 시작했습니다. 두 가지 주요 문제는 다음과 같습니다.

1) 내 테스트는 매우 빠르게 실행됩니다. 실행 파일로드의 오버 헤드, Q (Core) 응용 프로그램 (필요한 경우) 등을 설정하는 경우 종종 테스트 자체의 실행 시간을 왜소합니다! 각 실행 파일을 연결하면 많은 시간이 걸립니다.

점점 더 많은 클래스가 추가됨에 따라 오버 헤드가 계속 증가했고 곧 문제가되었습니다. 단위 테스트의 목표 중 하나는 너무 빨리 실행되는 안전망이 전혀 부담이되지 않는 것입니다. 신속하게는 그렇지 않습니다. 해결책은 여러 테스트 스위트를 하나의 실행 파일로 지구하는 것이며 (위와 같이) 이것은 대부분 수행 가능하지만 지원되지 않습니다 중요한 한계가 있습니다.

2) 비품 지원 없음 - 나를위한 거래 차단기.

잠시 후 Google 테스트로 전환했습니다. 훨씬 더 특징적이고 정교한 단위 테스트 프레임 워크 (특히 Google 모의에서 사용될 때) 및 1) 및 2) 및 2), 또한 Handy QtestLib 기능을 쉽게 사용할 수 있습니다. Qsignalspy 및 GUI 이벤트의 시뮬레이션 등과 같은 것은 전환하기가 약간 고통 스럽지만 고맙게도 프로젝트가 너무 멀리 발전하지 않았으며 많은 변경 사항이 자동화 될 수있었습니다.

개인적으로, 나는 미래의 프로젝트를 위해 Google Test를 통해 QTTest를 사용하지 않을 것입니다. 내가 볼 수있는 실제 이점이없고 중요한 단점이 있다면.

QT에 포함 된 단위 테스트 프레임 워크를 사용하지 않는 이유는 무엇입니까? An example : qttestlib 튜토리얼.

나는 gtest를 사용하여 라이브러리를 테스트했습니다 qsignalspy. Qsignalspy를 사용하여 신호를 잡으십시오. 슬롯을 직접 호출하여 (일반 방법과 같은) 테스트 할 수 있습니다.

QTTest는 QT 이벤트 루프/신호 디스패치가 필요한 부품을 테스트하는 데 주로 유용합니다. 각 테스트 사례에는 별도의 실행 가능이 필요한 방식으로 설계되었으므로 나머지 응용 프로그램에 사용되는 기존 테스트 프레임 워크와 충돌해서는 안됩니다.

(BTW, 응용 프로그램의 GUI가 아닌 부분에서도 QTCore를 사용하는 것이 좋습니다. 작업하는 것이 훨씬 좋습니다.)

MLVLJR 및 JOE의 솔루션을 확장하려면 하나의 테스트 클래스 당 완전한 QTTEST 옵션을 지원할 수도 있고 여전히 배치 플러스 로깅에서 모두 실행할 수 있습니다.

usage: 
  help:                                        "TestSuite.exe -help"
  run all test classes (with logging):         "TestSuite.exe"
  print all test classes:                      "TestSuite.exe -classes"
  run one test class with QtTest parameters:   "TestSuite.exe testClass [options] [testfunctions[:testdata]]...

헤더

#ifndef TESTRUNNER_H
#define TESTRUNNER_H

#include <QList>
#include <QTimer>
#include <QCoreApplication>
#include <QtTest>
#include <QStringBuilder>

/*
Taken from https://stackoverflow.com/questions/1524390/what-unit-testing-framework-should-i-use-for-qt
BEWARE: there are some concerns doing so, see  https://bugreports.qt.io/browse/QTBUG-23067
*/
class TestRunner : public QObject
{
   Q_OBJECT

public:
   TestRunner() : m_overallResult(0) 
   {
      QDir dir;
      if (!dir.exists(mTestLogFolder))
      {
         if (!dir.mkdir(mTestLogFolder))
            qFatal("Cannot create folder %s", mTestLogFolder);
      }
   }

   void addTest(QObject * test)
   {
      test->setParent(this);
      m_tests.append(test);
   }

   bool runTests(int argc, char * argv[]) 
   {
      QCoreApplication app(argc, argv);
      QTimer::singleShot(0, this, SLOT(run()));
      app.exec();

      return m_overallResult == 0;
   }

   private slots:
   void run() 
   {
      doRunTests();
      QCoreApplication::instance()->quit();
   }

private:
   void doRunTests() 
   {
      // BEWARE: we assume either no command line parameters or evaluate first parameter ourselves
      // usage: 
      //    help:                                        "TestSuite.exe -help"
      //    run all test classes (with logging):         "TestSuite.exe"
      //    print all test classes:                      "TestSuite.exe -classes"
      //    run one test class with QtTest parameters:   "TestSuite.exe testClass [options] [testfunctions[:testdata]]...
      if (QCoreApplication::arguments().size() > 1 && QCoreApplication::arguments()[1] == "-help")
      {
         qDebug() << "Usage:";
         qDebug().noquote() << "run all test classes (with logging):\t\t" << qAppName();
         qDebug().noquote() << "print all test classes:\t\t\t\t" << qAppName() << "-classes";
         qDebug().noquote() << "run one test class with QtTest parameters:\t" << qAppName() << "testClass [options][testfunctions[:testdata]]...";
         qDebug().noquote() << "get more help for running one test class:\t" << qAppName() << "testClass -help";
         exit(0);
      }

      foreach(QObject * test, m_tests)
      {
         QStringList arguments;
         QString testName = test->metaObject()->className();

         if (QCoreApplication::arguments().size() > 1)
         {
            if (QCoreApplication::arguments()[1] == "-classes")
            {
               // only print test classes
               qDebug().noquote() << testName;
               continue;
            }
            else
               if (QCoreApplication::arguments()[1] != testName)
               {
                  continue;
               }
               else
               {
                  arguments = QCoreApplication::arguments();
                  arguments.removeAt(1);
               }
         }
         else
         {
            arguments.append(QCoreApplication::arguments()[0]);
            // log to console
            arguments.append("-o"); arguments.append("-,txt");
            // log to file as TXT
            arguments.append("-o"); arguments.append(mTestLogFolder % "/" % testName % ".log,txt");
            // log to file as XML
            arguments.append("-o"); arguments.append(mTestLogFolder % "/" % testName % ".xml,xunitxml");
         }
         m_overallResult |= QTest::qExec(test, arguments);
      }
   }

   QList<QObject *> m_tests;
   int m_overallResult;
   const QString mTestLogFolder = "testLogs";
};

#endif // TESTRUNNER_H

자체 코드

#include "testrunner.h"
#include "test1" 
...

#include <QDebug>

int main(int argc, char * argv[]) 
{
    TestRunner testRunner;

    //your QTest compatible class here
    testRunner.addTest(new Test1);
    testRunner.addTest(new Test2);
    ...

    bool pass = testRunner.runTests(argc, argv);
    qDebug() << "Overall result: " << (pass ? "PASS" : "FAIL");

    return pass?0:1;
}

QT를 사용하는 경우 Qttest를 사용하는 것이 좋습니다. IS에는 UI를 테스트 할 수있는 시설이 있고 사용하기가 간단하기 때문입니다.

QTCore를 사용하는 경우 STL없이 할 수 있습니다. QT 클래스가 STL 상대보다 더 쉽게 사용하기 쉽다는 것을 자주 찾습니다.

나는 방금 이것을 가지고 놀았다. QTTest를 통해 Google 테스트를 사용하는 주요 장점은 Visual Studio에서 모든 UI 개발을 수행한다는 것입니다. Visual Studio 2012를 사용하고 설치하는 경우 Google 테스트 어댑터 테스트를 인식하고 테스트 탐색기에 포함시킬 수 있습니다. 이는 개발자가 코드를 작성할 때 사용할 수있는 것이 좋습니다. Google 테스트는 휴대용이기 때문에 Linux 빌드의 끝에 테스트를 추가 할 수도 있습니다.

앞으로 누군가가 C#과 같은 동시 테스트 도구 중 하나에 C ++에 대한 지원을 추가하기를 바라고 있습니다. ncrunch, Giles 그리고 연속 테스트.

물론, 누군가가 VS2012에 대한 또 다른 어댑터를 작성하여 테스트 어댑터에 QTTEST 지원을 추가 하여이 장점이 사라집니다! 누구든지 이것에 관심이 있다면 좋은 블로그 게시물이 있습니다. 새로운 Visual Studio Unit Test 어댑터 작성.

QTTest 프레임 워크를 사용한 Visual Studio Test 어댑터 도구 지원을 위해이 Visual Studio Extension을 사용하십시오. https://visualstudiogallery.msdn.microsoft.com/cc1fcd27-4e58-4663-951f-fb02d9ff3653

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top