Unit testing Qt:如何组织多个类的单元测试?
我有一个Qt单元测试(子)项目,它会生成一个类(main由Unit testing Qt:如何组织多个类的单元测试?,unit-testing,qt4,qt-creator,Unit Testing,Qt4,Qt Creator,我有一个Qt单元测试(子)项目,它会生成一个类(main由QTEST\u APPLESS\u main生成)。我可以在Qt Creator中作为控制台应用程序启动它 问:我如何向这个特定项目添加额外的类作为测试用例 如果这些类只有“test”槽(private Q\u槽),则不会调用这些方法,只调用带有QTEST\u APPLESS\u MAIN的类的方法 由于只能有一个main(..),我不能在项目中对多个类使用QTEST\u APPLESS\u main(正确吗?) 当然,我可以用一个包含m
QTEST\u APPLESS\u main
生成)。我可以在Qt Creator中作为控制台应用程序启动它
问:我如何向这个特定项目添加额外的类作为测试用例
private Q\u槽
),则不会调用这些方法,只调用带有QTEST\u APPLESS\u MAIN的类的方法
main(..)
,我不能在项目中对多个类使用QTEST\u APPLESS\u main
(正确吗?)main
的类手动“连接”(附加)类中的插槽,但这非常繁琐李>
那么,在单元测试项目中,在几个类上运行单元测试的最佳方法是什么呢
附言:
但是,在“”a中,我无法下载描述解决方案的zip文件
根据您链接到的解决方案,在单个Qt单元测试项目中测试两个(或更多)类的方法是确保要测试的每个类都有一个对应的测试类,并且您已经创建了一个执行每个测试类的自定义
int main
例如:
class TestClassA : public QObject
{
Q_OBJECT
public:
TestClassA();
...
private Q_SLOTS:
void testCase1();
...
};
class TestClassB : public QObject
{
Q_OBJECT
public:
TestClassB();
...
private Q_SLOTS:
void testCase2();
...
};
void TestClassA::testCase1()
{
// Define test here.
}
void TestClassB::testCase2()
{
// Define test here.
}
// Additional tests defined here.
// Note: This is equivalent to QTEST_APPLESS_MAIN for multiple test classes.
int main(int argc, char** argv)
{
int status = 0;
{
TestClassA tc;
status |= QTest::qExec(&tc, argc, argv);
}
{
TestClassB tc;
status |= QTest::qExec(&tc, argc, argv);
}
return status;
}
显然,不同的测试类可以分布在多个翻译单元上,然后使用
intmain
简单地包含在翻译单元中。不要忘记包含适当的.moc
文件。基于公认的答案,如果您使用的是C++11,您可能会对使用lambdas的解决方案感兴趣。它避免了您每次都编写相同的代码。虽然可以用函数替换lambda,但我认为lambda更干净
#include <QtTest>
#include "test1.h"
#include "test2.h"
int main(int argc, char** argv)
{
int status = 0;
auto ASSERT_TEST = [&status, argc, argv](QObject* obj) {
status |= QTest::qExec(obj, argc, argv);
delete obj;
};
ASSERT_TEST(new Test1());
ASSERT_TEST(new Test2());
return status;
}
#ifndef TEST1_H
#define TEST1_H
#包括
#包括“test1.h”
#包括“test2.h”
int main(int argc,字符**argv)
{
int status=0;
自动断言测试=[&status,argc,argv](QObject*obj){
状态|=QTest::qExec(obj、argc、argv);
删除obj;
};
ASSERT_TEST(新Test1());
ASSERT_TEST(新Test2());
返回状态;
}
#ifndef测试1_H
#定义TEST1_H
样品试验
#include <QtTest>
class Test1 : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testCase1();
};
#包括
类Test1:公共QObject
{
Q_对象
专用Q_插槽:
void testCase1();
};
在搜索相同的答案时,我从中找到了一个非常好的解决方案。他用一个容器创建一个名称空间,该容器注册所有创建的测试(通过DECLARE_TEST宏),然后使用它运行列表上的所有测试。我重写了它以适应我的代码,并将我的版本发布在这里(我的Qt Creator版本:4.1.0):
/*基于
* http://qtcreator.blogspot.de/2009/10/running-multiple-unit-tests.html
*/
#ifndef测试收集器
#定义TESTCOLLECTOR_H
#包括
#包括
#包括
#包括
命名空间测试收集器{
typedef std::map TestList;
内联测试列表&GetTestList()
{
静态测试列表;
退货清单;
}
内联int-RunAllTests(int-argc,char**argv){
int结果=0;
for(const auto&i:GetTestList()){
结果+=QTest::qExec(i.second.get(),argc,argv);
}
返回结果;
}
模板
类UnitTestClass{
公众:
UnitTestClass(常量std::string和pTestName){
auto&testList=TestCollector::GetTestList();
if(0==testList.count(pTestName)){
insert(std::make_pair(pTestName,std::make_shared());
}
}
};
}
#定义添加测试(类名)静态TestCollector::UnitTestClass\
测试(#类名);
#endif//TESTCOLLECTOR\u H
然后,只需在测试头中添加add_测试(类)行,如下所示:
#ifndef TESTRANDOMENGINES_H
#define TESTRANDOMENGINES_H
#include <QtTest>
#include "TestCollector.h"
class TestRandomEngines : public QObject
{
Q_OBJECT
private Q_SLOTS:
void test1();
};
ADD_TEST(TestRandomEngines)
#endif // TESTRANDOMENGINES_H
#如果NDEF测试引擎#
#定义TESTRANDOMENGINES\u H
#包括
#包括“TestCollector.h”
类TestRandomEngines:公共QObject
{
Q_对象
专用Q_插槽:
void test1();
};
添加测试(TestRandomEngines)
#endif//testrandom\u H
要运行所有测试,只需执行以下操作:
#include "TestCollector.h"
#include <iostream>
int main(int argc, char *argv[]) {
auto nFailedTests = TestCollector::RunAllTests(argc, argv);
std::cout << "Total number of failed tests: "
<< nFailedTests << std::endl;
return nFailedTests;
}
#包括“TestCollector.h”
#包括
int main(int argc,char*argv[]){
auto-nFailedTests=TestCollector::RunAllTests(argc,argv);
std::cout我这样做的方式:
- 创建一个通用的“细分”项目。
- 将测试代码置于C++库子项目中。
- 我使用的不是单元测试项目,而是控制台应用程序子项目。
- 将库链接到此控制台应用程序,不要忘记处理层次结构顶部.pro文件中的依赖项。
- 在这个控制台子项目中,定义尽可能多的测试类,并在同一个项目的main中启动它们
我基本上对做了一点改动。我使用以下代码来收集所有测试结果:
#include "testclassa.h"
#include "testclassb.h"
#include <QtTest>
#include <QDebug>
int main(int argc, char** argv){
int failedTests = 0;
TestClassA testClassA
TestClassB testClassB
failedTests += QTest::qExec(&testClassA, argc, argv);
failedTests += QTest::qExec(&testClassB, argc, argv);
if(failedTests > 0){
qDebug() << "total number of failed tests: " << failedTests;
}else{
qDebug() << "all tests passed :)";
}
return failedTests;
}
#包括“testclassa.h”
#包括“testclassb.h”
#包括
#包括
int main(int argc,字符**argv){
int failedTests=0;
TestClassA TestClassA
TestClassB TestClassB
failedTests+=QTest::qExec(&testClassA、argc、argv);
failedTests+=QTest::qExec(&testClassB,argc,argv);
如果(失败测试>0){
qDebug()使用CMake而不是QMake构建,并添加两个测试目标
add_executable(firstTest tst_testfirst.cpp)
add_test(NAME firstTest COMMAND firstTest)
add_executable(secondTest tst_testsecond.cpp)
add_test(NAME secondTest COMMAND secondTest)
tst_testfirst.cpp和tst_testsecond.cpp都有自己的QTEST_主线
Qt Creator将运行这两个测试类。如果从命令行运行它们,则使用“ctest”运行测试.直截了当地说,我应该早点看一下QTEST_APPLESS_MAIN DEFINE。我刚刚注意到你是回答这个问题的人,他之前也对我的另一个问题发表了评论,所以我怀疑你可以很好地解释这一区别。如果你有两个单独的文件(.cpp和.h),你不需要包含.moc动态创建对象的原因是什么?您也可以传递一个引用,这样您就不必处理对象销毁。auto ASSERT_TEST=[&status,argc,argv](QObject&obj){status |=QTest::qExec(&obj,argc,argv)};ASSERT_TEST(Test1())
@christopheis我只是喜欢在
add_executable(firstTest tst_testfirst.cpp)
add_test(NAME firstTest COMMAND firstTest)
add_executable(secondTest tst_testsecond.cpp)
add_test(NAME secondTest COMMAND secondTest)