十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何加快 GoogleMock mock 类编译速度:把构造函数和析构函数移到 .cc 文件

如何加快 GoogleMock mock 类编译速度:把构造函数和析构函数移到 .cc 文件 如何加快 GoogleMock mock 类编译速度把构造函数和析构函数移到 .cc 文件【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest如果你的工程里定义了包含多个MOCK_METHOD的 mock 类而且这个头文件被很多.cc文件#include编译时很可能明显变慢——尤其是 mock 的方法签名种类越多、翻译单元越多时。本文介绍 GoogleMock 官方 Cookbook 里给出的一个针对性优化把 mock 类的构造函数和析构函数的定义从类体内移到单独的.cc文件中让编译器只为该类生成一次构造函数和析构函数从而加快编译。为什么 mock 类的编译会变慢gmock_cook_book.md 中 “Making the Compilation Faster” 一节给出的解释是编译一个 mock 类所花费的大部分时间实际消耗在生成它的构造函数和析构函数上因为这两个函数会执行非平凡的任务例如校验verification各 mock 方法上设置的 expectations每个 mock 方法的签名不同类型就不同编译器需要为它们分别生成对应的构造函数/析构函数因此当一个 mock 类 mock 了很多种不同签名的方法时编译会“really slow”原文用词。关键机制在于只要构造函数和析构函数没有在头文件中定义编译器就会在每个使用这个 mock 类的翻译单元里重新生成它们。也就是说头文件被 N 个文件包含构造/析构逻辑就要生成 N 次。优化做法头文件只声明.cc 文件给定义Cookbook 给出的改法分两步。1. 修改头文件声明构造函数和析构函数改动前mock_foo.h中不声明构造函数和析构函数编译器会在每个用到该类的翻译单元中生成它们以下为文档示例// File mock_foo.h. ... class MockFoo : public Foo { public: // Since we dont declare the constructor or the destructor, // the compiler will generate them in every translation unit // where this mock class is used. MOCK_METHOD(int, DoThis, (), (override)); MOCK_METHOD(bool, DoThat, (const char* str), (override)); ... more mock methods ... };改动后文档示例在类体内显式声明构造函数和析构函数但不给定义// File mock_foo.h. ... class MockFoo : public Foo { public: // The constructor and destructor are declared, but not defined, here. MockFoo(); virtual ~MockFoo(); MOCK_METHOD(int, DoThis, (), (override)); MOCK_METHOD(bool, DoThat, (const char* str), (override)); ... more mock methods ... };2. 新建 .cc 文件给出定义按 Cookbook 的示例在mock_foo.cc中写// File mock_foo.cc. #include path/to/mock_foo.h // The definitions may appear trivial, but the functions actually do a // lot of things through the constructors/destructors of the member // variables used to implement the mock methods. MockFoo::MockFoo() {} MockFoo::~MockFoo() {}这里的#include path/to/mock_foo.h需要替换成你的头文件实际所在路径构造函数和析构函数体虽然看起来是空的但文档明确说明它们会通过实现各 mock 方法所用的成员变量的构造/析构做大量工作所以不能删掉这两行定义只保留声明。改完后的效果是即使你的 mock 头文件被 N 个文件#include编译器也只需要生成一次它的构造函数和析构函数编译速度会明显提升文档原文“resulting in a much faster compilation”。验证改动是否正确文档本身没有给出量化的编译时间对比验证时按下面两步检查即可构建仍然通过改动后重新构建你的测试目标。因为构造函数和析构函数现在只在mock_foo.cc中定义这个文件必须加入你的构建系统CMake 的add_executable/target_sources或 Bazel 的srcs等并参与链接否则其他引用该 mock 类的目标会因找不到定义而链接失败测试行为不变改动只影响编译方式不改变 mock 语义。重新跑一遍使用这个 mock 的测试原有通过/失败结果应与改动前一致mock 对象析构时自动校验 expectations 的行为不受影响。如果你的测试工程用 CMake 构建可参考 CMake 快速上手 中声明测试目标和运行ctest的方式来做这一步验证。适用条件与限制该方案针对的是编译慢的 mock 类。文档给出的适用判断是mock 了多种不同签名的方法、且头文件被多个翻译单元包含时收益才明显对只有一个或两个 mock 方法的小类优化空间有限改动范围仅限构造/析构这两个函数MOCK_METHOD声明本身仍然留在头文件里不影响EXPECT_CALL、ON_CALL的用法如果某个目标确实从不编译mock_foo.cc例如某些只链接部分目标的环境它会因为找不到构造/析构定义而无法链接这时要么保证该文件在所有使用方参与编译要么回退到原来“头文件内不声明”的写法。更多 mock 用法匹配器、actions、线程等可继续在 gmock_cook_book.md 中查阅基础概念可以先看 gmock_for_dummies.md。【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表