当前位置: 首页 > news >正文

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:

  1. 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 &registry
= 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库设置环境变量:

  1. 在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以后&#xff0c;可以将它们组织成Te…...

《水利水电安全员考试各题型对比分析及应对攻略》

《水利水电安全员考试各题型对比分析及应对攻略》 单选题&#xff1a; 特点&#xff1a;四个选项中只有一个正确答案&#xff0c;相对难度较小。主要考查对基础知识的掌握程度。 应对攻略&#xff1a;认真审题&#xff0c;看清题目要求。对于熟悉的知识点&#xff0c;直接选择…...

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、真泛型、类型复杂、支持事务、报错信息不完整&#xff08;启动事…...

IMX6ULL驱动开发uboot篇02

目录 网络操作 第零步&#xff1a;先将网线跟电脑接好&#xff0c;打开串口连接到开发板上&#xff0c;然后上电&#xff0c;让UBoot停下来 第一步&#xff1a;查看我们的网线构成的虚拟子网是哪一个 第二步&#xff1a;我们必须把虚拟机的网卡模式从NAT改成桥接&#xff0c…...

智谱AI-FunctionCall

智谱AI-FunctionCall 编写FuncationCall大模型的函数调用&#xff0c;先直观的感受一下的感受下FunctionCall的魅力 文章目录 智谱AI-FunctionCall[toc]1-参考网址2-思路整理3-代码拆件1-[非核心]两个业务函数2-[非核心]业务函数的JsonSchema定义3-[核心]FunctionCall的调用1-打…...

数据保险箱:备份文件的关键价值与自动化实践

在信息化社会&#xff0c;数据已经成为我们生活、工作和学习的核心组成部分。无论是企业机密、个人隐私&#xff0c;还是创意作品、研究数据&#xff0c;它们都以数字形式存在于我们的电子设备中。然而&#xff0c;数据如同脆弱的玻璃制品&#xff0c;稍有不慎就可能面临丢失或…...

数字电路基础——逻辑门

逻辑门是数字电子技术中的基本构建块。这些组件用于对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初步认识整体架构

第一章&#xff1a;人工智能之不同数据类型及其特点梳理 第二章&#xff1a;自然语言处理(NLP)&#xff1a;文本向量化从文字到数字的原理 第三章&#xff1a;循环神经网络RNN&#xff1a;理解 RNN的工作机制与应用场景(附代码) 第四章&#xff1a;循环神经网络RNN、LSTM以及GR…...

【从模仿到超越:AIGC的崛起与AGI的终极梦想】

一、基本概念 1. AIGC&#xff08;人工智能生成内容&#xff09; 定义&#xff1a;基于人工智能技术生成文本、图像、音频、视频等数字内容的方法。技术基础&#xff1a;依赖深度学习模型&#xff08;如GPT、DALL-E、Stable Diffusion&#xff09;和自然语言处理&#xff08;…...

标量、向量、矩阵与张量:从维度理解数据结构的层次

在数学和计算机科学中&#xff0c;维度描述了数据结构的复杂性&#xff0c;而标量、向量、矩阵、张量则是不同维度的数据表示形式。它们的关系可以理解为从简单到复杂的扩展&#xff0c;以下是详细解析&#xff1a; 1. 标量&#xff08;Scalar&#xff09;&#xff1a;0维数据 …...

windows 上删除 node_modules

在 Windows 11 上&#xff0c;你可以通过命令行来删除 node_modules 文件夹并清除 npm 缓存。以下是具体步骤&#xff1a; 删除 node_modules 打开命令提示符&#xff08;Command Prompt&#xff09;或终端&#xff08;PowerShell&#xff09;。 导航到项目目录。你可以使用 …...

单例模式的五种实现方式

1、饿汉式 ①实现&#xff1a;在类加载的时候就初始化实例 ②优点&#xff1a;线程安全 ③缺点&#xff1a;实例在类加载的时候创建&#xff0c;可能会浪费资源 //饿汉式 public class EagerSingleton{private EagerSingleton(){} //私有构造方法private static EagerSingle…...

启智平台华为昇腾910B使用MS-Swift微调Janus-Pro-7/1B

最近想要微调一下DeepSeek出品的Janus多模态大模型 利用启智平台的昇腾910B国产计算卡进行大模型的微调 查看了一下MS-Swift支持了Janus模型的微调&#xff0c;LLamafactory好像暂时还不支持该模型的微调 看到了MS-Swift有单独对昇腾的支持&#xff0c;因此首先要安装swift&…...

蓝桥试题:传球游戏(二维dp)

一、题目描述 上体育课的时候&#xff0c;小蛮的老师经常带着同学们一起做游戏。这次&#xff0c;老师带着同学们一起做传球游戏。 游戏规则是这样的&#xff1a;n 个同学站成一个圆圈&#xff0c;其中的一个同学手里拿着一个球&#xff0c;当老师吹哨子时开始传球&#xff0…...

迷你世界脚本小地图接口:Mapmark

小地图接口&#xff1a;Mapmark 彼得兔 更新时间: 2023-10-25 10:33:48 具体函数名及描述如下: 序号 函数名 函数描述 1 newShape(...) 新增一个形状(线&#xff0c;矩形&#xff0c;圆形) 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功能&#xff0c;可以将C写的软件到浏览器中运行&#xff0c;最近一段时间正在研究这方便内容&#xff0c;普通的控件响应都能实现&#xff0c;今天主要为大家分享如何将FFmpeg中的功能应用到浏览器中。 开发环境&#xff1a;window11&#xff0c;Qt6.8.2…...

Java阻塞队列深度解析:高并发场景下的安全卫士

一、阻塞队列的核心价值 在电商秒杀系统中&#xff0c;瞬时涌入的10万请求如果直接冲击数据库&#xff0c;必然导致系统崩溃。阻塞队列如同一个智能缓冲带&#xff0c;通过流量削峰和异步解耦两大核心能力&#xff0c;成为高并发系统的核心组件。 二、Java阻塞队列实现类对比 …...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...