QTS单元测试框架
1.QTS单元测试框架介绍
目前QTS项目采用C/C++语言,而CppUnit就是xUnit家族中的一员,它是一个专门面向C++的单元测试框架。因此,QTS采用CppUnit测试框架是比较理想的选择。
CppUnit按照层次来管理测试,最底层的就是TestCase,当有了几个TestCase以后,可以将它们组织成TestFixture。在TestFixture中,可以建立被测试的类的实例,并编写TestCase对类实例进行测试,多个TestFixture可以通过TestSuite来对测试进行管理。
通过派生TestFixture类来设计某个类或某组相关功能的单元测试,Fixture定义公共函数setUp()初始化每个成员变量,tearDown()来释放setUp中使用的资源。在每个测试中,CPPUNIT_ASSERT(bool)来判断某个函数和表达式的正确性,在派生类的声明中,通过CPPUNIT_TEST来增加对应的测试函数,通过CPPUNIT_TEST_SUITE和CPPUNIT_TEST_SUITE_END来分装所有的测试函数,规定这些测试函数执行的顺序。
2.QTS单元测试框架搭建
2.1CppUnit 介绍
A、CppUnit源代码组成
CppUnit测试框架的源代码可以到 http://sourceforge.net/projects/cppunit/ 上下载。下载解压后,你将看到如下文件夹:

主要的文件夹有:
· doc: CppUnit的说明文档。另外,代码的根目录,还有三个说明文档,分别是INSTALL,INSTALL-unix,INSTALL-WIN32.txt。
· examples: CpppUnit提供的例子,也是对CppUnit自身的测试,通过它可以学习如何使用CppUnit测试框架进行开发。
· include: CppUnit头文件。
· src: CppUnit源代码目录。
B、初识CppUnit测试环境
解压源代码包后, CppUnit结构如下:
1、进入example文件夹,用VC打开examples.dsw。我们先来看看CppUnit自带的测试例子。这些例子都是针对CppUnit自身的单元测试集,一方面这是CppUnit作者开发CppUnit框架过程中写的测试用例,另一方面,我们可以通过这些例子来学习如何在我们自己的工程中添加测试用例。
2、将CppUnitTestApp工程设为Active Project(Win32 Debug),编译后运行,则可以看到CppUnit的基于GUI方式进行单元测试TestRunner的界面。点击“Run”,将会看到如图二所示界面:

这是一个针对CppUnit的单元测试结果,它表明刚才我们做了11个测试,全部通过。
点击“Browse”,我们还可以选择想要进行的单元测试,如图三:

2.2 CppUnit单元测试环境搭建
第一步:编译CppUnit 静态库文件*.lib和动态库文件*.dll:
- CppUnit的lib和dll
CppUnit为我们提供了两套框架库,一个为静态的lib,一个为动态的dll。
cppunit project:静态lib
cppunit_dll project:动态dll和lib
在开发中我们可以根据实际情况作出选择。进入src文件夹,打开CppUnitLibraries.dsw。分别编译这两个project,输出位置均为lib文件夹。
在开发中我们可以根据实际情况作出选择。进入src文件夹,打开CppUnitLibraries.dsw。在菜单上选择Build->Batch Build..->Rebuild All,输出位置均为lib文件夹。
为了方便开发,我们把这些编译出来的lib和dll拷贝到我们自己建立的一个文件夹中(当然你也可以不这么做),例如F:\Mytest\lib\,同时我们也把CppUnit源代码中include文件夹copy到我们自己的include文件夹下。
第二步:建立基于对话框的工程
打开VC,在File菜单项下选择New,建立基于dialog的工程。工程名Project name、存放位置Location可以自己决定,其他选项如下:

按OK确认后,进入如下界面。选择Dialog based选项,按Finish按钮后,一个空的基于对话框的工程就建立起来了。

第三步:屏蔽工程对话框
在工程CouterTest.cpp文件中(本指南中为该文件名,实际学习时根据自己的工程文件名而变),找到BOOL CCounterTestApp::InitInstance()方法,将如下附带代码注释掉:也就是代码中带*的部分
BOOL CCounterTestApp::InitInstance()
{AfxEnableControlContainer();// Standard initialization// If you are not using these features and wish to reduce the size// of your final executable, you should remove from the following// the specific initialization routines you do not need.#ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL
#elseEnable3dControlsStatic(); // Call this when linking to MFC statically
#endif/*CCounterTestDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK}else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel}*/// Since the dialog has been closed, return FALSE so that we exit the// application, rather than start the application's message pump.return FALSE;
}
由于我们希望这个Project运行后显示的是图2这样的CppUnit自带的界面,所以我们需要在Instance()中屏蔽掉原有的对话框(蓝色部分注释掉),代之以CppUnit的GUI。
第四步:实现CppUnit测试执行器,并将测试套添加到测试执行器中。
A、在BOOL CCounterTestApp::InitInstance()中,添加如下附加注释的代码:
BOOL CCounterTestApp::InitInstance()
{AfxEnableControlContainer();// Standard initialization// If you are not using these features and wish to reduce the size// of your final executable, you should remove from the following// the specific initialization routines you do not need.#ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL
#elseEnable3dControlsStatic(); // Call this when linking to MFC statically
#endif//添加CppUnit的MFC类型的测试执行器CppUnit::MfcUi::TestRunner runner; //为被测试类(这里是CCounter)定义一个测试工厂(这里取名叫CounterTest):CppUnit::TestFactoryRegistry ®istry
= CppUnit::TestFactoryRegistry::getRegistry("CounterTest");//并将工厂添加到测试执行器中
runner.addTest( registry.makeTest() );//运行执行器,显示执行器GUI界面runner.run(); /*CCounterTestDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK}else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel}*/// Since the dialog has been closed, return FALSE so that we exit the// application, rather than start the application's message pump.return FALSE;
}
B、由于在BOOL CCounterTestApp::InitInstance()中引用了CppUnit的类,所以在文件开始处要添加如下头文件:
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/mfc/TestRunner.h>
第五步:添加被测对象CCounter。
将被测对象所在文件(CounterMod.h和CounterMod.cpp) 添加到工程中:

第六步:在工程中为被测对象CCounter编写测试类文件MyTest(可以自定义文件名):
按照下面示图加入测试类的*.h文件和*.cpp文件:


MyTest.h中的代码如下:
#include "cppunit/extensions/HelperMacros.h"class IsCodeLineTest : public CppUnit::TestFixture {// 声明一个TestSuiteCPPUNIT_TEST_SUITE( IsCodeLineTest);// 添加测试用例到TestSuite, 定义新的测试用例需要在这儿声明一下CPPUNIT_TEST( Test1 );// TestSuite声明完成CPPUNIT_TEST_SUITE_END();public:// 定义测试用例void Test1 ();};
MyTest.cpp中的代码如下(注意头文件要做相应的修改):
#include "stdafx.h"#include "MyTest.h"
#include "CounterMod.h"// 把这个TestSuite注册到名字为"CounterTest"的工厂中
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( IsCodeLineTest,"CounterTest" );#define RET_OK 0
#define RET_FAIL 1void IsCodeLineTest::Test1()
{//定义输入参数int bIsComment;CString szFileLine;//定义期望输出int iOkReturn;int iOkIsComment;//定义测试实际输出int iResult;CCounter m_counter;//用例输入szFileLine = "int a";bIsComment = false;//期望输出iOkReturn = RET_OK;iOkIsComment = false;//驱动被测函数iResult = m_counter.IsCodeLine(szFileLine,bIsComment);//结果比较CPPUNIT_ASSERT_EQUAL(iOkReturn,iResult);CPPUNIT_ASSERT_EQUAL(iOkIsComment,bIsComment);
}
第七步:加入CppUnit 库文件:

把CppUnit相关的lib文件和dll文件(cppunitd.lib,cppunitd_dll.lib,testrunnerd.lib)加入到工程中:

第八步:设置头文件和lib库文件路径、打开RTTI开关、给dLL库设置环境变量:
- 在VC的tools/options/directories/include files和library files中设置CppUnit include文件路径和lib文件路径:

在你的VC project中打开RTTI开关。具体位置Project Settings/C++/C++ Language:

C、为TestRunnerd.dll设置环境变量
TestRunnerd.dll为我们提供了基于GUI的测试环境。为了让我们的测试程序能正确的调用它,需要把TestRunnerd.dll拷贝到你的工程路径下。或者最简单的方法是在操作系统的环境变量Path中添TestRunnerd.dll的路径,这样是最省事的。
第九步:编译执行。编译连接成功后,运行测试,出现下面的界面,表示测试用例Test1运行成功.

相关文章:
QTS单元测试框架
1.QTS单元测试框架介绍 目前QTS项目采用C/C语言,而CppUnit就是xUnit家族中的一员,它是一个专门面向C的单元测试框架。因此,QTS采用CppUnit测试框架是比较理想的选择。 CppUnit按照层次来管理测试,最底层的就是TestCase,当有了几个TestCase以后,可以将它们组织成Te…...
《水利水电安全员考试各题型对比分析及应对攻略》
《水利水电安全员考试各题型对比分析及应对攻略》 单选题: 特点:四个选项中只有一个正确答案,相对难度较小。主要考查对基础知识的掌握程度。 应对攻略:认真审题,看清题目要求。对于熟悉的知识点,直接选择…...
sqlite3 c++ client选择; c++环境搭建 : abseil-cpp | fnc12/sqlite_orm
sqlite3 c client选择 今日20250305 2.4K星: 7月前最后提交核心: SRombauts/SQLiteCpp.git : 薄封装、命令式sql、非orm、支持事务2.4K星: 1月前最后提交核心: fnc12/sqlite_orm.git : 厚封装、非侵入、真orm、真泛型、类型复杂、支持事务、报错信息不完整(启动事…...
IMX6ULL驱动开发uboot篇02
目录 网络操作 第零步:先将网线跟电脑接好,打开串口连接到开发板上,然后上电,让UBoot停下来 第一步:查看我们的网线构成的虚拟子网是哪一个 第二步:我们必须把虚拟机的网卡模式从NAT改成桥接,…...
智谱AI-FunctionCall
智谱AI-FunctionCall 编写FuncationCall大模型的函数调用,先直观的感受一下的感受下FunctionCall的魅力 文章目录 智谱AI-FunctionCall[toc]1-参考网址2-思路整理3-代码拆件1-[非核心]两个业务函数2-[非核心]业务函数的JsonSchema定义3-[核心]FunctionCall的调用1-打…...
数据保险箱:备份文件的关键价值与自动化实践
在信息化社会,数据已经成为我们生活、工作和学习的核心组成部分。无论是企业机密、个人隐私,还是创意作品、研究数据,它们都以数字形式存在于我们的电子设备中。然而,数据如同脆弱的玻璃制品,稍有不慎就可能面临丢失或…...
数字电路基础——逻辑门
逻辑门是数字电子技术中的基本构建块。这些组件用于对1和0进行操作,可以将它们组合起来创建其他构建块,并设计出如锁存器、触发器、加法器、移位寄存器等电路。 七种主要的逻辑门类型: 一、基本逻辑门 1.1 与门(AND gate) 1.1.1 逻辑运算规则 与门有多个输入端和一个输出…...
爬虫逆向:脱壳工具BlackDex的详细使用
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、BlackDex简介二、下载与安装三、基本使用步骤3.1 启动BlackDex3.2 导入目标APK文件3.3 开始脱壳3.4 查看脱壳结果四、后续分析4.1 使用 JADX 反编译 Dex 文件4.2 使用 Apktool 反编译 Dex 文件4.3 JD-GUI4.4 dex2ja…...
JavaScript中的Math()
目录 一、Math() 1.1floor() 1.2ceil() 1.3round() 1.4random() 1.5max() 1.6min() 1.7pow() 1.8sqrt() 1.9trunc() 二、parseFloat() 三、toFixed() 四、toString() 4.1Number类型转换为字符串 4.2Boolean类型转换为字符串 4.3Date()类型转换为字符串 4.4Arr…...
深度学习模型Transformer初步认识整体架构
第一章:人工智能之不同数据类型及其特点梳理 第二章:自然语言处理(NLP):文本向量化从文字到数字的原理 第三章:循环神经网络RNN:理解 RNN的工作机制与应用场景(附代码) 第四章:循环神经网络RNN、LSTM以及GR…...
【从模仿到超越:AIGC的崛起与AGI的终极梦想】
一、基本概念 1. AIGC(人工智能生成内容) 定义:基于人工智能技术生成文本、图像、音频、视频等数字内容的方法。技术基础:依赖深度学习模型(如GPT、DALL-E、Stable Diffusion)和自然语言处理(…...
标量、向量、矩阵与张量:从维度理解数据结构的层次
在数学和计算机科学中,维度描述了数据结构的复杂性,而标量、向量、矩阵、张量则是不同维度的数据表示形式。它们的关系可以理解为从简单到复杂的扩展,以下是详细解析: 1. 标量(Scalar):0维数据 …...
windows 上删除 node_modules
在 Windows 11 上,你可以通过命令行来删除 node_modules 文件夹并清除 npm 缓存。以下是具体步骤: 删除 node_modules 打开命令提示符(Command Prompt)或终端(PowerShell)。 导航到项目目录。你可以使用 …...
单例模式的五种实现方式
1、饿汉式 ①实现:在类加载的时候就初始化实例 ②优点:线程安全 ③缺点:实例在类加载的时候创建,可能会浪费资源 //饿汉式 public class EagerSingleton{private EagerSingleton(){} //私有构造方法private static EagerSingle…...
启智平台华为昇腾910B使用MS-Swift微调Janus-Pro-7/1B
最近想要微调一下DeepSeek出品的Janus多模态大模型 利用启智平台的昇腾910B国产计算卡进行大模型的微调 查看了一下MS-Swift支持了Janus模型的微调,LLamafactory好像暂时还不支持该模型的微调 看到了MS-Swift有单独对昇腾的支持,因此首先要安装swift&…...
蓝桥试题:传球游戏(二维dp)
一、题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。 游戏规则是这样的:n 个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球࿰…...
迷你世界脚本小地图接口:Mapmark
小地图接口:Mapmark 彼得兔 更新时间: 2023-10-25 10:33:48 具体函数名及描述如下: 序号 函数名 函数描述 1 newShape(...) 新增一个形状(线,矩形,圆形) 2 deleteShape(...) 删除一个形状 3 setShapeColor(...) 设置…...
从零开始在Windows使用VMware虚拟机安装黑群晖7.2系统并实现远程访问
文章目录 前言1.软件准备2. 安装VMware17虚拟机3.安装黑群晖4. 安装群晖搜索助手5. 配置黑群晖系统6. 安装内网穿透6.1 下载cpolar套件6.2 配置群辉虚拟机6.3 配置公网地址6.4 配置固定公网地址 总结 前言 本文主要介绍如何从零开始在Windows系统电脑使用VMware17虚拟机安装黑…...
Qt6.8.2创建WebAssmebly项目使用FFmpeg资源
Qt6新出了WebAssmebly功能,可以将C写的软件到浏览器中运行,最近一段时间正在研究这方便内容,普通的控件响应都能实现,今天主要为大家分享如何将FFmpeg中的功能应用到浏览器中。 开发环境:window11,Qt6.8.2…...
Java阻塞队列深度解析:高并发场景下的安全卫士
一、阻塞队列的核心价值 在电商秒杀系统中,瞬时涌入的10万请求如果直接冲击数据库,必然导致系统崩溃。阻塞队列如同一个智能缓冲带,通过流量削峰和异步解耦两大核心能力,成为高并发系统的核心组件。 二、Java阻塞队列实现类对比 …...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
