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运行成功.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dify + ollama + deepseek-r1+ stable-diffusion 构建绘画智能体

故事背景 stable-diffusion 集成进 dify 后&#xff0c;我们搭建一个小智能体&#xff0c;验证下文生图功能 业务流程 #mermaid-svg-6nSwwp69eMizP6bt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6nSwwp69eMiz…

分享几个论文校对相关的deepseek提示词

论文校对 1.检查这段文字是否有语法或风格错误&#xff1a;[在此处粘贴您的文本]。 2.审查我的[文件类型&#xff0c;例如&#xff0c;“论文”]中的这一段落是否有语法或风格错误&#xff1a;[在此处粘贴您的文本]。 3.请审查我关于[具体主题&#xff0c;例如&#xff0c;…

【极光 Orbit•STC8A-8H】02. STC8 单片机工程模板创建

【极光 Orbit•STC8A-8H】02. STC8 单片机工程模板创建 七律 单片机 小小芯片大乾坤&#xff0c;集成世界在其中。 初学虽感千重难&#xff0c;实践方知奥妙通。 今天的讲法和过去不同&#xff0c;直接来一个多文件模块化的工程模板创建&#xff0c;万事开头难&#xff0c;…

mac安装nvm=>node=>nrm

下载并安装 NVM 运行以下命令下载并安装 NVM&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash 配置环境变量 vim ~/.zshrc 按 i 将如下代码复制进去&#xff0c;controlc &#xff0c;再按 :wq完成编辑 export NVM_DIR…

K8S学习之基础十一:k8s中容器钩子

容器钩子 容器钩子分为post-start和pre-stop post-start&#xff1a;容器启动后执行的命令 pre-stop&#xff1a;容器关闭前执行的命令&#xff0c;可用于优雅关闭 # 分别定义两个钩子&#xff0c;启动pod后更新index.html&#xff0c;关闭pod前正常关闭服务 vi post-pre.…

K8s 1.27.1 实战系列(三)安装网络插件

Kubernetes 的网络插件常见的有 Flannel 和 Calico ,这是两种主流的 CNI(容器网络接口)解决方案,它们在设计理念、实现方式、性能特征及适用场景上有显著差异。以下是两者的综合对比分析: 一、Flannel 和 Calico 1. 技术基础与网络实现 Flannel 核心机制:基于 Overlay …

【五.LangChain技术与应用】【24.LangChain RAG文本向量化与存储:智能检索的核心技术】

凌晨三点,北京中关村的某栋办公楼依然灯火通明。28岁的算法工程师小李盯着屏幕上的代码,突然拍案而起:"终于成了!"他开发的智能客服系统在连续失败78次后,首次准确识别出用户"我想换个能打游戏的便宜手机"的真实需求——需要兼顾游戏性能和价格的机型…

深度学习五大模型:CNN、Transformer、BERT、RNN、GAN详细解析

卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09; 原理 &#xff1a;CNN主要由卷积层、池化层和全连接层组成。卷积层通过卷积核在输入数据上进行卷积运算&#xff0c;提取局部特征&#xff1b;池化层则对特征图进行下采样&#xff0c;降低特征维度&…

特征分解(Eigen decomposition)在深度学习中的应用与理解

特征分解在深度学习中的应用与理解 特征分解&#xff08;Eigendecomposition&#xff09;是线性代数中的一个核心工具&#xff0c;在深度学习领域有着广泛的应用&#xff0c;尤其是在涉及矩阵操作和概率模型时。对于研究者来说&#xff0c;理解特征分解不仅有助于掌握数学基础…

分布式ID生成方案:数据库号段、Redis与第三方开源实现

分布式ID生成方案&#xff1a;数据库号段、Redis与第三方开源实现 引言 在分布式系统中&#xff0c;全局唯一ID生成是核心基础能力之一。本文针对三种主流分布式ID生成方案&#xff08;数据库号段模式、Redis方案、第三方开源框架&#xff09;进行解析&#xff0c;从实现原理…

rabbitmq-amqp事务消息+消费失败重试机制+prefetch限流

1. 安装和配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency><dependency> <groupId>com.fasterxml.jackson.core</groupId> <arti…

【Python】05、Python运算符

文章目录 1.算术运算符2.赋值运算符3.关系运算符4.逻辑运算符4.1 布尔值逻辑运算4.2 非布尔值的逻辑运算符 5.条件运算符6.运算符优先级 运算符也称为操作符&#xff0c;可以对一个或多个值进行运算或各种操作。比如、-、都属于运算符 1.算术运算符 加法 如果是两个字符串之间…

2025-03-06 学习记录--C/C++-PTA 习题6-6 使用函数输出一个整数的逆序数

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>int reverse( int number );int main…

简记_硬件系统设计之需求分析要点

目录 一、 功能需求 二、 整体性能需求 三、 用户接口需求 四、 功耗需求 五、 成本需求 六、 IP和NEMA防护等级需求 七、 认证需求 功能需求 供电方式及防护 供电方式&#xff1a;市电供电、外置直流稳压电源供电、电池供电、PoE&#xff08;Power Over Ether…

[原创](Modern C++)现代C++的关键性概念: 利用“概念(Concepts)“,可以优雅地约束模板参数

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi、XCode、Eclipse…

Self-Pro: A Self-Prompt and Tuning Framework for Graph Neural Networks

Self-Pro: A Self-Prompt and Tuning Framework for Graph Neural Networks ​#paper/GFM/GNN-BASED#​ #paper/⭐⭐⭐#​ 注意&#xff1a;这篇文章是每个图一个GCN模型&#xff0c;而不是所有图一个GCN 模型 算是最早的涉及异配图的prompt了 贡献和动机&#xff1a; 非对…

宝塔 Linux 计划任务中添加运行项目网站PHP任务-定时任务

一、指定php版运行&#xff0c; cd /www/wwwroot/www.xxx.com/ && /www/server/php/56/bin/php think timedtasks start >> /tmp/timedtasks.log 2>&1 二、不指定php版 cd /www/wwwroot/www.xxx.com/ && php think timedtasks start >> …

【电控笔记z29】扰动估测器DOB估测惯量J-摩擦系数B

基本原理 扰动估测器的核心思想是通过向电机系统施加特定的扰动信号&#xff0c;观察系统响应的变化&#xff0c;然后利用系统的动态模型和控制理论来估计未知参数&#xff0c;如惯量和摩擦系数 。一般基于电机的运动方程建立数学模型&#xff0c;结合观测到的电机实际运行数据…

要查看 SQLite 数据库中的所有表,可以通过查询 SQLite 的系统表 sqlite_master

要查看 SQLite 数据库中的所有表&#xff0c;可以查询 SQLite 的系统表 sqlite_master。 每个 SQLite 数据库都包含一个名为 sqlite_master 的系统表。该表定义了数据库的模式&#xff0c;存储了数据库中所有表、索引、视图和触发器等对象的信息。 通过查询 sqlite_master&am…

如何在Spring Boot中读取JAR包内resources目录下文件

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 以下是如何在Spring Boot中读取JAR包内resources目录下文件的教程&#xff0c;分为多种方法及详细说明&#xff1a; 方法1&#xff1a;使用 ClassPathResour…