新闻中心
c++如何实现一个简单的单元测试断言宏_c++手写测试框架核心【项目】
_ASSERT宏实现轻量级断言:条件为假时打印文件名、行号、表达式字符串,递增全局失败计数但不中止程序;_ASSERT_EQ支持值比对与调试输出,用do-while(0)防歧义,自动捕获左右值并打印。

用 C++ 手写一个轻量级单元测试框架,核心就是实现一个能捕获失败、报告位置、不崩溃程序的断言宏。不需要依赖 Google Test 或 Catch2,几行宏 + 全局计数器就能跑起来。
基础断言宏:\_ASSERT
最简版本的目标是:当条件为假时,打印文件名、行号、表达式,并让测试计数器标记“失败”,但不 abort() 或 throw,以便继续执行后续测试用例。
- 用 do-while(0) 包裹避免宏展开歧义
- 用 __FILE__ 和 __LINE__ 记录位置
- 用 #expr 把表达式转成字符串用于打印
- 失败时递增全局失败计数,并用 std::cerr 输出提示
// 示例:简单断言宏
#include <iostream>
#include <string>
<p>int g_tests_run = 0;
int g_tests_failed = 0;</p><h1>define _ASSERT(expr) \</h1><pre class='brush:php;toolbar:false;'>do { \
++g_tests_run; \
if (!(expr)) { \
++g_tests_failed; \
std::cerr << "[FAIL] " << __FILE__ << ":" << __LINE__ \
<< " - '" << #expr << "'\n"; \
} \
} while(0)支持自定义消息的断言:\_ASSERT_EQ
实际测试中常需比对两个值,比如 _ASSERT_EQ(a, b)。它本质仍是断言,但要展开为 (a) == (b),同时把 a、b 的值也打出来,方便调试。
- 用双重括号避免宏参数被意外解析(如 _ASSERT_EQ(x++, y))
- 用 std::cout 打印值,需确保类型支持流输出(基础类型、std::string 等都 OK)
- 可选:加一层 static_cast
(a), static_cast 防止未使用警告(b)
// 示例:相等断言
Openflow
一键极速绘图,赋能行业工作流
88
查看详情
#define _ASSERT_EQ(lhs, rhs) \
do { \
++g_tests_run; \
auto _lhs_val = (lhs); \
auto _rhs_val = (rhs); \
if (_lhs_val != _rhs_val) { \
++g_test
s_failed; \
std::cerr << "[FAIL] " << __FILE__ << ":" << __LINE__ \
<< " - '" << #lhs << " == " << #rhs \
<< "' -> " << _lhs_val << " != " << _rhs_val << '\n'; \
} \
} while(0)测试函数注册与运行机制
没有测试发现机制?手动注册就行。用函数指针数组 + 全局初始化列表,或更简洁的“自动注册”技巧:利用全局对象构造函数执行注册。
- 定义测试函数类型:using test_func = void(*)();
- 用静态 vector 存储所有测试函数(线程不安全但单测够用)
- 写一个 TEST(name) 宏:生成匿名函数 + 自动 push 到 vector
- main() 中遍历调用,每个测试前重置失败计数(或单独统计每例)
// 示例:TEST 宏 + 运行器
std::vector<test_func> g_test_registry;
<h1>define TEST(name) \</h1><pre class='brush:php;toolbar:false;'>void test_##name(); \
struct register_##name { \
register_##name() { g_test_registry.push_back(test_##name); } \
}; \
static register_##name register_instance_##name; \
void test_##name()int main() { std::cout failed == 0) { std::cout " #name 0 ? 1 : 0; }
进阶:支持跳过、预期失败、作用域隔离
真要工程化,可以加几个小扩展:
- _SKIP("reason"):直接输出 SKIP 并 return,不计入失败
- _EXPECT_FAIL(expr):期望 expr 为 false,若为 true 则报错(反向断言)
- 每个 TEST 函数内用 { ... } 包裹,天然提供局部作用域,避免变量名冲突
- 用 RAII 类(如 Timer、LogGuard)在测试前后自动打时间戳或清日志缓冲区
基本上就这些。不复杂但容易忽略的是:宏里别用 return(会破坏 do-while 结构),别忘了重置计数器,还有——所有宏末尾不要加分号,由使用者加。
以上就是c++++如何实现一个简单的单元测试断言宏_c++手写测试框架核心【项目】的详细内容,更多请关注其它相关文章!
# c++
# 单元测试
# 但不
# 行号
# 如何实现
# google
# stream
# ios
# ai
# go
# 大连企业网站优化有哪些
# 吴江网络营销推广外包
# 重庆网站建设优化
# 联想是否用了seo
# 保定公司推广营销公司
# seo平台靠谱吗
# 北屯网站优化公司
# 北京响应式网站建设企业
# 快排seo排名软件下载
# 宜春营销推广多少钱
# 几个
# 进阶
# 运算符
# 的是
# 比对
# 什么用
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
解决 Express.js 中 PUT 请求密码修改失败的路由配置指南
解决Flask中Quill编辑器内容提交失败及TypeError的指南
抖音怎么赚钱_抖音创作者变现方法与途径指南
怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】
Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐
taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】
必由学官网入口 必由学教师登录入口
如何在Promise链中优雅地中断后续then执行
最新韩小圈网页版登录入口_官网在线观看官方链接
理解J*aScript Promise的微任务队列与执行顺序
Tabulator表格日期时间排序问题及自定义解决方案
优化HTML表单样式:解决输入框焦点跳动与元素间距问题
深入理解Google Cloud Datastore查询:祖先路径与数据一致性
QQ官网正版登录链接 QQ在线登录入口最新
Promise错误处理:在catch后终止链式then执行的策略
狙击外星人小游戏开始_狙击外星人小游戏立即开始
Win11如何使用Windows Sandbox Win11沙盒功能开启与使用教程【详解】
React中useState与局部变量:理解组件状态管理与渲染机制
腾讯视频怎么举报不良内容_腾讯视频内容举报流程与违规信息处理方法
html5 app怎么运行环境_配html5 app运行环境【教程】
如何有效阻止外部脚本意外修改内联样式的高度属性
React Hooks最佳实践:动态组件状态管理的组件化方案
HTML5原生日期选择器与jQuery UI:实现日期选择器的联动与程序化控制
J*aScript类型检查_j*ascript代码规范
Composer如何处理Git子模块(submodule)依赖_Composer与Git Submodule的对比与选择
照顾宝贝2小游戏免费秒玩入口
从J*aScript对象中精确提取指定属性的教程
怎么在mac上运行html代码_mac运行html代码方法【指南】
Win11怎么关闭触摸屏_Windows 11禁用HID符合标准触摸屏
如何仅使用CSS更改登录界面背景图像图标的颜色
电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】
J*a递归快速排序中静态变量导致数据累积问题的解决方案
冬*霸灯泡不亮怎么办_浴霸取暖灯一盏不亮的灯座清洁修复法
c++中的std::basic_string的SSO优化_c++短字符串优化深度解析
windows10怎么查看本机ip_windows10命令提示符ipconfig使用
纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析
Win11截图该按哪些键 Win11截屏完整流程解析【教程】
TikTok网页版直接登录 TikTok网页端官方平台入口
CSS布局中意外空白:解决padding-top导致的顶部间距问题
拼多多赚钱渠道_拼多多收益来源
C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器
必由学官方平台入口 必由学在线课堂登录地址
AO3网页版合集入口 Archive of Our Own同人作品浏览指南
J*a应用程序首次运行自动创建文件与目录的最佳实践
CSS Flexbox如何实现多行排列_flex-wrap wrap自动换行显示
机构:以往存储涨价周期小米利润率实际上有所改善 能转嫁给消费者等
快手官方唯一登录入口 谨防山寨钓鱼网站
Spyder启动失败:字体文件权限拒绝错误解决方案
Surface怎么安装系统 微软Surface Pro U盘重装win11教程
Python:递归比较文件夹内容并找出特定类型文件的差异


2025-12-07
浏览次数:次
返回列表
s_failed; \
std::cerr << "[FAIL] " << __FILE__ << ":" << __LINE__ \
<< " - '" << #lhs << " == " << #rhs \
<< "' -> " << _lhs_val << " != " << _rhs_val << '\n'; \
} \
} while(0)