我刚开始一个新项目,需要一些交叉平台GUI,我们已选择脱如GUI的框架。

我们需要一个单元的测试框架,太。直到大约一年前我们用一个内部开发的单元测试框架C++的项目,但我们现在正在过渡到使用谷歌测试新的项目。

没有任何人有任何经验与使用谷歌测试脱-应用程序?是QtTest/QTestLib一个更好的选择吗?

我仍然不知道我们有多想要使用夸脱在非GUI项目的部分-我们可能会喜欢只是使用STL/提高在核心码有一个小型接口脱基于GUI。

编辑: 它看起来像许多人都倾向QtTest.是否有任何人有任何经验,将这一连续整合服务器?此外,这将在我看来,具有处理一个单独的应用程序,为每个新试验情况会引起很大的磨擦。是否有任何良好方式来解决?不夸脱的创造者有一个好的方法处理这些测试的情况下或者你会需要有一个项目每测的情况吗?

有帮助吗?

解决方案

我不知道QTestLib比一个框架,另一个在这样的笼统“更好”。有一两件事,它做得很好,这是提供给测试基于Qt应用程序的好方法。

您可以QTEST融入新的谷歌测试基础设置。我还没有尝试过,但基于QTestLib是如何架构,好像它不会是太复杂了。

纯QTestLib笔试有,你可以使用,一些XSLT转换以及转换为所需要的格式为持续集成服务器的-xml选项。然而,很多依赖于你去与CI服务器。我可以想象这同样适用于GTEST。

每个测试用例单个测试应用从未引起了很多摩擦,对我来说这取决于有一个构建系统,会做管理的测试用例的建设和执行一份体面的工作。

我不知道的Qt Creator中任何可能要求每个测试用例一个单独的项目,但自从上次我看了看Qt Creator中它可能已经改变。

我也建议用QtCore粘附和保持从STL程。使用QtCore整个将使处理需要Qt的数据类型更容易的GUI位。你将不必担心在这种情况下,从一种数据类型转换成另一种。

其他提示

您不必创建单独的测试应用程序。

:只是在类似于该一个一个独立的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文档中描述的很好,即使它似乎是很多人非常有用。

要追加到乔的回答。

下面是一个小的头我使用(testrunner.h),含有工具类产卵事件循环(这是,例如,为了测试排队信号槽连接和数据库需要)和“跑步” QTEST兼容类:

#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(核心)应用程序(如果需要)等的开销往往相形见绌测试本身的运行时间!联的每个可执行占用了大量的时间,也

在开销只是不停地为加入越来越多类增加,并很快成为了一个问题 - 的单元测试的目标之一是有运行如此之快,是不是负担,在所有的安全网,这是迅速成为并非如此。该解决方案是多glob的测试套件成一个可执行程序,并且当(如上所示),这是主要是做-能,它是不支持并具有重要的限制。

2)否夹具支持 - 一个交易断路器为我

所以,一段时间后,我跳槽到谷歌测试 - 这是(与谷歌模拟使用时尤为突出)远更多的其他功能和成熟的单元测试框架,解决了1)和2),而且,你仍然可以很容易地使用方便QTestLib功能,如QSignalSpy和GUI事件的模拟等,这是一个痛苦位的切换,但幸运的是,该项目已不太远先进和许多的变化可以自动化。

就个人而言,我不会使用QtTest在谷歌测试为将来的项目 - 如果报价,我看不出有什么真正的优势,并具有重要的缺点

为什么不使用包括在Qt的所述单元测试框架? 一个例子: QtTestLib教程

我单元使用GTEST和 QSignalSpy 测试了我们的库。使用QSignalSpy捕获的信号。可以直接(像普通的方法)调用插槽测试它们。

QtTest是用于测试所需要的Qt的事件循环/信号调度部件大多是有用的。它的设计,每个测试用例需要一个单独的可执行文件,因此它不应该与用于应用程序的其余任何现有的测试框架发生冲突的方式。

(顺便说一句,我强烈建议使用QtCore甚至为应用程序的非GUI部件,它是好得多的工作。)

要扩展mlvljr的和乔的解决方案,我们甚至可以支持每一个测试类完整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,由于有设施测试用户界面和简单易用。

如果您使用QtCore,你也许可以做到没有STL。我经常发现的Qt类更容易比STL同行使用。

我刚刚在玩这个。主要优势的使用谷歌测试过QtTest对我们来说,我们做我们所有的用户界面开发在Visual Studio.如果你使用Visual Studio2012年安装的 谷歌测试适配器 你可以得到VS认识的测试,并包括他们在其试验。这是伟大的开发者能够利用为他们编写代码,因为谷歌测试是便携式的我们还可以添加测试的结束我们的Linux的建立。

我希望在未来某人将会增加支持C++的一个并行的检测工具,C#有一样 NCrunch, 吉尔斯ContinuousTests.

当然,你可能会找人写的另一个转接器,用于VS2012,增加了QtTest支持,以测试适配器在这种情况下,这种优势消失!如果有人有兴趣在这有一个很好的博客 创作一个新的视觉工作室单元的测试适配器.

Visual Studio测试适配的工具,支持与QtTest框架使用这些工作室扩展: https://visualstudiogallery.msdn.microsoft.com/cc1fcd27-4e58-4663-951f-fb02d9ff3653

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top