C++单元测试框架gtest实战:从断言机制到CI集成的完整指南
1. 初识gtest为什么C开发者都绕不开这个测试框架写了十多年C我见过太多项目在测试这件事上翻车。早期大家靠assert加打印日志后来有人写个main函数手动调一遍所有接口再后来CI流水线跑起来才发现没有像样的单元测试框架整个质量体系就是空中楼阁。gtestGoogle Test就是在这个背景下进入我视野的——它不是最轻量的也不是语法最优雅的但它是目前C社区里工程化程度最高、生态最完整、踩坑资料最多的单元测试框架之一。这篇文章面向三类人一是刚接触C单元测试、不知道从哪下手的新手二是用过其他框架比如Catch2、Boost.Test想横向对比的老手三是团队里被安排去搭测试基建、需要一份能直接抄作业的落地指南的工程师。我会从gtest的核心设计思路讲起把断言机制、测试夹具、参数化测试、死亡测试这些关键能力拆开揉碎再给出一套完整的实操流程和常见问题排查表。全文基于我实际在多个中型C项目里落地gtest的经验不是翻译官方文档而是把文档里没写清楚、只有踩过坑才知道的东西补上。先给一个直观的定位gtest是Google在2008年前后开源的一套C单元测试框架基于BSD许可证跨平台支持Linux、Windows、macOS能跟CMake、Bazel等构建系统无缝集成。它的核心价值在于把“写测试”这件事从“写一堆if-else加打印”变成“用声明式的方式描述预期行为”并且提供了测试发现、用例组织、失败报告、死亡测试等一整套工程化能力。你不需要自己写测试运行器不需要自己管理测试注册甚至不需要自己处理断言失败后的流程控制——这些gtest都替你做了。2. gtest的核心设计思路与方案选型考量2.1 为什么是xUnit架构而不是自研轮子gtest遵循的是xUnit测试框架的经典架构模式这个模式最早来自JUnit后来被几乎所有主流语言的测试框架继承。它的核心抽象只有四个测试用例Test、测试套件Test Suite、断言Assertion、测试运行器Test Runner。你写的每个TEST()宏展开后就是一个测试用例多个测试用例可以归到一个测试套件里断言负责判断结果是否符合预期运行器负责发现、执行、报告。为什么选这个架构而不是自己写个简单的测试脚本我试过在早期项目里用Python脚本调C可执行文件做黑盒测试也试过用shell脚本跑一堆assert结论是当测试用例超过50个、需要分组管理、需要参数化、需要统计失败率的时候自研轮子的维护成本会指数级上升。gtest的xUnit架构把这些都标准化了你只需要关注“测什么”和“预期是什么”剩下的交给框架。2.2 断言机制ASSERT和EXPECT的取舍逻辑gtest的断言分两大类ASSERT_*系列和EXPECT_*系列。这个设计看起来简单但背后有明确的取舍逻辑。ASSERT_*在失败时会直接终止当前测试函数后面的代码不执行EXPECT_*失败时只记录失败继续往下跑。很多人刚开始用的时候会纠结“到底用哪个”我的经验法则是如果后续代码依赖前面断言的结果比如指针判空后再解引用用ASSERT_*如果后续代码可以独立验证其他行为用EXPECT_*。举个例子你测试一个返回指针的函数如果指针为空后面解引用就会崩溃这时候必须用ASSERT_NE(ptr, nullptr)。但如果你测试一个计算函数想同时验证返回值和输出参数两个断言互不依赖那就用EXPECT_EQ这样一次运行能看到所有失败点不用改一次跑一次。2.3 测试夹具什么时候该用Test Fixturegtest提供了TEST_F宏来支持测试夹具Test Fixture也就是让多个测试用例共享同一套初始化代码。这个功能不是必须的但用对了能大幅减少重复代码。判断标准很简单如果多个测试用例需要操作同一组对象、同一份数据、同一套环境那就抽一个夹具类出来继承::testing::Test在SetUp()里做初始化在TearDown()里做清理。我见过有人把所有测试都塞进一个夹具里结果SetUp里初始化了十几个不相关的对象每个测试用例只用到其中一两个。这是典型的过度设计。夹具的粒度应该跟测试套件的语义边界对齐比如“测试一个数据库连接池”可以是一个夹具“测试一个字符串工具类”就不需要夹具直接写TEST就行。2.4 参数化测试解决“同一逻辑多组输入”的重复劳动参数化测试是gtest里被低估的功能。当你需要验证同一个逻辑在不同输入下的行为时比如“加法函数对正数、负数、零、边界值都正确”如果写四个独立的TEST代码重复度很高。gtest提供了TEST_P宏配合INSTANTIATE_TEST_SUITE_P来实现参数化你只需要写一次测试逻辑然后传入多组参数。这个功能在算法类、工具类、协议解析类的测试里特别有用。我做过一个JSON解析器的测试用参数化测试把几十组合法和非法输入一次性覆盖代码量比写几十个独立测试少了三分之二而且新增用例只需要在参数列表里加一行。3. 核心细节解析与实操要点3.1 环境搭建从源码编译到CMake集成gtest的获取方式有三种源码直接编译、包管理器安装、CMake的FetchContent拉取。我推荐第三种因为版本可控、跨平台一致、不需要手动处理依赖路径。具体做法是在CMakeLists.txt里写include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.14.0 ) FetchContent_MakeAvailable(googletest)然后链接目标add_executable(my_tests test_main.cpp) target_link_libraries(my_tests PRIVATE gtest gtest_main)这里有个细节gtest_main提供了默认的main函数如果你的测试不需要自定义入口直接链接它就行。但如果你需要做全局初始化比如初始化日志系统就要自己写main链接gtest而不是gtest_main。注意gtest从1.13版本开始要求C141.14要求C14以上。如果你的项目还在用C11需要锁定到1.12版本。这个版本兼容性问题在升级构建系统时经常被忽略导致编译报一堆模板错误。3.2 断言宏的完整分类与使用场景gtest的断言宏按比较类型分常用的有断言类型ASSERT版本EXPECT版本适用场景布尔判断ASSERT_TRUE/ASSERT_FALSEEXPECT_TRUE/EXPECT_FALSE条件成立性验证数值比较ASSERT_EQ/NE/LT/LE/GT/GEEXPECT_EQ/NE/LT/LE/GT/GE整数、浮点数、指针比较字符串比较ASSERT_STREQ/STRNEEXPECT_STREQ/STRNEC风格字符串内容比较浮点比较ASSERT_FLOAT_EQ/DOUBLE_EQEXPECT_FLOAT_EQ/DOUBLE_EQ浮点数近似比较异常判断ASSERT_THROW/NO_THROWEXPECT_THROW/NO_THROW异常抛出行为验证死亡测试ASSERT_DEATHEXPECT_DEATH进程崩溃行为验证浮点比较这里有个坑EXPECT_FLOAT_EQ用的是4个ULP的误差范围不是绝对误差。如果你需要自定义误差得用EXPECT_NEAR(val1, val2, abs_error)。我见过有人用EXPECT_EQ比较两个浮点数结果因为精度问题测试随机失败排查了半天才发现是断言选错了。3.3 测试套件与用例的命名规范gtest的TEST(TestSuiteName, TestName)宏里两个参数分别代表测试套件名和测试用例名。命名规范不是强制的但直接影响测试报告的可读性。我的习惯是套件名用“被测模块名”或“被测类名”用例名用“行为描述_条件”的格式。比如TEST(StringUtilTest, Split_EmptyInput_ReturnsEmptyVector) { // ... }这样跑测试的时候失败信息里直接能看到“哪个模块的什么行为在什么条件下失败了”不用去翻代码。反过来如果写成TEST(Test1, Case1)过两个月你自己都不知道在测什么。3.4 测试夹具的SetUp和TearDown执行顺序夹具类的SetUp()在每个测试用例执行前调用TearDown()在每个测试用例执行后调用。如果同时存在构造函数/析构函数和SetUp/TearDown执行顺序是构造函数 → SetUp → 测试体 → TearDown → 析构函数。这个顺序意味着构造函数里适合做不依赖虚函数调用的初始化SetUp里适合做需要多态行为的初始化。实操心得TearDown里不要抛异常。gtest在TearDown抛异常时的行为是未定义的可能导致测试进程直接崩溃而且崩溃信息很难定位。清理逻辑如果可能失败用EXPECT_*记录失败而不是抛异常。4. 实操过程与核心环节实现4.1 从零搭建一个可运行的测试工程假设我们有一个简单的计算器模块提供加、减、乘、除四个函数。项目结构如下project/ ├── CMakeLists.txt ├── src/ │ └── calculator.cpp │ └── calculator.h └── test/ └── calculator_test.cppcalculator.h里声明四个函数calculator.cpp里实现。测试文件calculator_test.cpp的内容#include gtest/gtest.h #include calculator.h TEST(CalculatorTest, Add_TwoPositiveNumbers_ReturnsSum) { EXPECT_EQ(add(2, 3), 5); } TEST(CalculatorTest, Divide_ByZero_ThrowsException) { EXPECT_THROW(divide(10, 0), std::invalid_argument); } TEST(CalculatorTest, Multiply_NegativeAndPositive_ReturnsNegative) { EXPECT_EQ(multiply(-3, 4), -12); }CMakeLists.txt里加上测试目标enable_testing() add_executable(calculator_test test/calculator_test.cpp src/calculator.cpp) target_link_libraries(calculator_test PRIVATE gtest gtest_main) add_test(NAME calculator_test COMMAND calculator_test)编译后运行./calculator_test你会看到类似这样的输出[] Running 3 tests from 1 test suite. [----------] Global test environment set-up. [----------] 3 tests from CalculatorTest [ RUN ] CalculatorTest.Add_TwoPositiveNumbers_ReturnsSum [ OK ] CalculatorTest.Add_TwoPositiveNumbers_ReturnsSum (0 ms) [ RUN ] CalculatorTest.Divide_ByZero_ThrowsException [ OK ] CalculatorTest.Divide_ByZero_ThrowsException (0 ms) [ RUN ] CalculatorTest.Multiply_NegativeAndPositive_ReturnsNegative [ OK ] CalculatorTest.Multiply_NegativeAndPositive_ReturnsNegative (0 ms) [----------] 3 tests from CalculatorTest (0 ms total) [----------] Global test environment tear-down [] 3 tests from 1 test suite ran. (0 ms total) [ PASSED ] 3 tests.4.2 参数化测试的完整实现假设我们要测试add函数在多组输入下的行为用参数化测试的写法class AddTest : public ::testing::TestWithParamstd::tupleint, int, int {}; TEST_P(AddTest, Add_VariousInputs_ReturnsExpected) { auto [a, b, expected] GetParam(); EXPECT_EQ(add(a, b), expected); } INSTANTIATE_TEST_SUITE_P( AddCases, AddTest, ::testing::Values( std::make_tuple(1, 1, 2), std::make_tuple(-1, -1, -2), std::make_tuple(0, 0, 0), std::make_tuple(INT_MAX, 0, INT_MAX), std::make_tuple(INT_MIN, 0, INT_MIN) ) );这里用了std::tuple作为参数类型C17的结构化绑定让取值很简洁。INSTANTIATE_TEST_SUITE_P的第一个参数是实例名前缀会出现在测试报告里方便区分不同参数组。4.3 死亡测试的实操与注意事项死亡测试用来验证代码在特定条件下会崩溃或退出。比如验证一个断言宏在条件不满足时确实会终止进程TEST(DeathTest, AssertionFails_ProcessAborts) { EXPECT_DEATH({ int* p nullptr; *p 42; }, ); }死亡测试的执行机制比较特殊gtest会fork一个子进程执行测试体然后检查子进程是否异常终止。这意味着死亡测试里不能有复杂的资源管理也不能依赖父进程的状态。注意死亡测试在Windows上的行为跟Linux不同Windows下用的是CreateProcess而不是fork某些场景下可能不稳定。如果项目需要跨平台死亡测试要谨慎使用或者只在Linux CI上跑。4.4 测试过滤与运行参数gtest提供了丰富的命令行参数来控制测试执行。常用的有# 只跑名字包含Add的测试 ./calculator_test --gtest_filter*Add* # 排除某个套件 ./calculator_test --gtest_filter-CalculatorTest.* # 重复跑100次检测偶发失败 ./calculator_test --gtest_repeat100 # 失败后继续跑不提前退出 ./calculator_test --gtest_break_on_failure0 # 输出XML格式报告方便CI集成 ./calculator_test --gtest_outputxml:report.xml--gtest_repeat这个参数在排查偶发失败时特别有用。我遇到过一个多线程相关的bug单次跑测试总是通过用--gtest_repeat1000跑了半小时才复现出来。5. 常见问题与排查技巧实录5.1 编译链接问题速查表问题现象可能原因解决方法undefined reference totesting::Test::Test()没链接gtest库在target_link_libraries里加gtest重复定义main同时链接了gtest_main和自己写的main二选一只保留一个C标准不匹配的模板错误gtest版本要求的C标准高于项目设置升级项目C标准或降级gtest版本Windows下LNK2019运行库配置不一致MT/MD确保gtest和项目用同一运行库选项5.2 测试运行时的典型故障故障一测试用例没被发现。最常见的原因是测试文件没被编译进可执行文件或者TEST宏写在了命名空间里但没加对应的using。gtest的测试注册是静态初始化阶段完成的如果链接器把测试目标文件优化掉了测试就不会注册。解决办法是确保测试文件被显式链接或者在CMake里用target_sources明确列出。故障二断言失败信息不显示文件名和行号。这通常是因为编译时没加调试信息-g或者用了NDEBUG宏把断言禁用了。gtest的断言不依赖assert宏但EXPECT_DEBUG_DEATH这类调试相关的断言会受NDEBUG影响。故障三浮点比较随机失败。前面提过EXPECT_FLOAT_EQ用的是ULP误差不是绝对误差。如果被测函数的计算路径不同即使数学上等价浮点结果也可能有微小差异。解决办法是改用EXPECT_NEAR并指定合理的绝对误差。故障四死亡测试在CI上超时。死亡测试fork子进程如果子进程进入死循环父进程会一直等。gtest默认没有超时机制需要在CI层面加超时控制或者用EXPECT_DEATH的变体配合::testing::ExitedWithCode来精确匹配退出码。5.3 独家避坑技巧第一个技巧用TEST_P的时候参数生成器里的表达式只会在注册阶段求值一次。如果你在Values()里写了有副作用的表达式比如Values(getNextId())它不会在每个测试用例执行时重新求值。需要动态参数的话用ValuesIn配合一个生成器函数。第二个技巧夹具的SetUp里不要用ASSERT_*。ASSERT_*在SetUp里失败会导致测试体不执行但TearDown仍然会跑。如果TearDown依赖SetUp里创建的资源而SetUp中途失败了TearDown就会访问空指针。正确做法是在SetUp里用EXPECT_*或者手动检查资源是否创建成功。第三个技巧测试命名里不要用下划线开头或结尾。虽然gtest不禁止但下划线开头的标识符在C标准里是保留给实现的某些编译器会警告。用Add_TwoPositive_ReturnsSum这种格式就很好。第四个技巧CI里跑测试一定要加--gtest_outputxml。这样失败信息会被结构化输出方便CI系统解析和展示。纯文本输出在日志里翻起来很痛苦尤其是测试用例上百个的时候。6. 从单测到持续集成gtest在工程流水线中的位置gtest本身只是个测试框架但它的价值在CI流水线里会被放大。我通常会把测试目标分成三层单元测试gtest、集成测试gtest加真实依赖、端到端测试外部脚本。单元测试要求毫秒级完成每次代码提交都跑集成测试分钟级合并请求时跑端到端测试十分钟以上每日构建跑。gtest的XML输出可以直接被Jenkins、GitLab CI、GitHub Actions解析。在GitHub Actions里一个典型的C测试工作流是这样的- name: Configure CMake run: cmake -B build -DCMAKE_BUILD_TYPEDebug - name: Build run: cmake --build build - name: Test run: cd build ctest --output-on-failurectest是CMake的测试运行器它会自动发现add_test注册的测试目标并汇总结果。配合--output-on-failure只有失败的测试才会打印详细输出日志干净很多。实操心得在CI里给测试加超时。gtest本身没有超时机制一个死循环的测试会卡住整个流水线。用ctest --timeout 30给每个测试设30秒上限超时自动杀掉并标记失败。7. 我个人在实际操作中的体会gtest上手不难但用好需要理解它的设计哲学测试是代码不是脚本。这意味着测试代码也要遵循命名规范、也要做代码审查、也要避免重复。我见过太多项目把测试写成一次性脚本跑通就扔后面需求变了测试全废。正确的做法是把测试当成产品代码的一部分来维护用夹具消除重复用参数化覆盖边界用命名表达意图。另一个体会是不要追求100%覆盖率。gtest能统计覆盖率配合gcov/lcov但覆盖率数字本身没有意义。有意义的是“关键路径有没有被覆盖”“边界条件有没有被验证”“回归bug有没有对应的测试用例”。我通常会把覆盖率目标定在70%到80%剩下的精力花在测试质量而不是数量上。最后分享一个小技巧如果你在维护一个老项目历史代码没有测试不要试图一次性补全。从最近修改的模块开始改一个函数就补一个测试用--gtest_filter只跑相关测试逐步扩大覆盖范围。这样既不会影响开发节奏又能让测试资产随时间积累。gtest的测试发现机制让新增测试零成本你只需要写TEST宏剩下的交给框架。

相关新闻

【机器人控制】三台非全体移动机器人分散式领跟控制、基于李雅普诺夫的轨迹跟踪以及三角与柱形动态切换编队控制Matlab实现

【机器人控制】三台非全体移动机器人分散式领跟控制、基于李雅普诺夫的轨迹跟踪以及三角与柱形动态切换编队控制Matlab实现

✅作者简介:热爱科研的Matlab仿真开发者,擅长数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和数学建模资料 &…

2026/10/13 11:40:13 阅读更多 →
ArcGIS图斑编号工具:基于空间排序的图斑自动编号方法详解

ArcGIS图斑编号工具:基于空间排序的图斑自动编号方法详解

简介:面向GIS开发者的ArcGIS图斑编号工具,用于对矢量图斑按自上而下、从左到右的规则统一编号,解决地块、建筑物等空间实体标识杂乱的问题,适用于土地利用规划、城市设计与空间数据管理场景。资源为zip压缩包,共39个文…

2026/10/13 11:40:13 阅读更多 →
Agent技能体系构建实战:从定义编排到落地的完整经验

Agent技能体系构建实战:从定义编排到落地的完整经验

最近在梳理智能体项目时,我发现一个很有意思的现象:很多团队在搭建 Agent 应用时,最头疼的往往不是模型选型,也不是 Prompt 调优,而是"明明模型能力很强,为什么落不了地"。说到底,问题…

2026/10/13 11:40:13 阅读更多 →

最新新闻

AI写作成本怎么降?率零降流程拆解与批量生产实操指南

AI写作成本怎么降?率零降流程拆解与批量生产实操指南

第一次看到“率零降AI教程”这个说法的时候,我第一反应是标题党。市面上号称白菜价的AI写作课太多了,点进去基本都是把公开提示词换个包装,真正能落地的东西少得可怜。后来被一个做内容代运营的朋友拉着一起跑了整套流程,才明白标…

2026/10/13 12:20:16 阅读更多 →
Tye 多仓库(Multirepo)编排:跨仓库引用 tye.yaml 与 Git 依赖的完整指南

Tye 多仓库(Multirepo)编排:跨仓库引用 tye.yaml 与 Git 依赖的完整指南

开发工具微服务云原生CLI 【免费下载链接】tye Tye is a tool that makes developing, testing, and deploying microservices and distributed applications easier. Project Tye includes a local orchestrator to make developing microservices easier and the ability to …

2026/10/13 12:20:16 阅读更多 →
抖音无水印批量下载完整指南:从单个视频到直播的四类实战场景

抖音无水印批量下载完整指南:从单个视频到直播的四类实战场景

抖音无水印批量下载完整指南:从单个视频到直播的四类实战场景 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallbac…

2026/10/13 12:20:16 阅读更多 →
机械硬盘异响排查与修复:西数Data Lifeguard检测全攻略

机械硬盘异响排查与修复:西数Data Lifeguard检测全攻略

半夜三更,机箱里突然传来一声清脆的“咔哒”,紧接着又是几声,你瞬间从椅子上坐直,脑子里闪过四个字:硬盘完了。说真的,凡是用过机械硬盘的人,多少都被这种声音吓过。尤其是西部数据的盘&#xf…

2026/10/13 12:20:16 阅读更多 →
Flutter鸿蒙适配实践:Skia渲染引擎原理与踩坑指南

Flutter鸿蒙适配实践:Skia渲染引擎原理与踩坑指南

去年我在一家中厂做跨端基建,内部有个工具必须跑在同一套自研终端上,顺手把 Flutter 也编译了过去。当时没想太多,以为换个 SDK、改个入口就完了,结果被渲染链路里一个引擎逼着啃了整整两周,那个引擎就是 Skia 渲染引擎…

2026/10/13 12:20:16 阅读更多 →
Linux终端复用工具 screen 详解:SSH断线任务不丢失

Linux终端复用工具 screen 详解:SSH断线任务不丢失

1. 没有screen之前,远程任务是怎么丢的 1.1 一次断网事故的复盘 先交代一个我自己的翻车现场。前几年有一次在服务器上跑一个数据迁移任务,大概要跑两三个小时,文件数量几十万个,我直接用SSH连着服务器,前台执行脚本&…

2026/10/13 12:19:15 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →