跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 单元测试
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C++单元测试 = '''单元测试'''是软件开发中的一种测试方法,用于验证代码的最小可测试单元(通常是函数或类方法)是否按预期工作。在C++中,单元测试可以帮助开发者快速发现和修复错误,提高代码质量,并确保代码在后续修改中不会引入回归问题。 == 什么是单元测试? == 单元测试是一种自动化测试技术,专注于测试代码的独立部分(即“单元”)。在C++中,一个单元可以是一个函数、一个类方法或一个模块。单元测试的主要目标是: * 验证代码的正确性 * 提高代码的可维护性 * 促进重构时的安全性 * 作为代码行为的文档 == 为什么需要单元测试? == 单元测试在C++开发中至关重要,原因包括: * '''早期错误检测''':在开发过程中尽早发现逻辑错误。 * '''回归测试''':确保修改不会破坏现有功能。 * '''文档作用''':测试用例可作为代码行为的示例。 * '''设计改进''':编写可测试的代码通常会带来更好的设计。 == C++单元测试框架 == C++有多种流行的单元测试框架,以下是几个常用选项: {| class="wikitable" |- ! 框架名称 ! 特点 |- | Google Test | 功能丰富,支持参数化测试和死亡测试 |- | Catch2 | 简单易用,仅需单头文件 |- | Boost.Test | 功能强大,与Boost库集成 |- | CppUnit | 基于xUnit架构 |} == 使用Google Test进行单元测试 == Google Test(gtest)是C++中最流行的单元测试框架之一。以下是一个基本示例: <syntaxhighlight lang="cpp"> #include <gtest/gtest.h> // 被测函数 int Add(int a, int b) { return a + b; } // 测试用例 TEST(AdditionTest, PositiveNumbers) { EXPECT_EQ(Add(2, 3), 5); EXPECT_EQ(Add(10, 20), 30); } TEST(AdditionTest, NegativeNumbers) { EXPECT_EQ(Add(-2, -3), -5); EXPECT_EQ(Add(-10, 20), 10); } int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } </syntaxhighlight> '''输出示例''': <pre> [==========] Running 2 tests from 1 test suite. [----------] Global test environment set-up. [----------] 2 tests from AdditionTest [ RUN ] AdditionTest.PositiveNumbers [ OK ] AdditionTest.PositiveNumbers (0 ms) [ RUN ] AdditionTest.NegativeNumbers [ OK ] AdditionTest.NegativeNumbers (0 ms) [----------] 2 tests from AdditionTest (0 ms total) [==========] 2 tests from 1 test suite ran. (1 ms total) [ PASSED ] 2 tests. </pre> == 测试驱动开发(TDD) == 测试驱动开发是一种先写测试再实现功能的开发方法。流程如下: <mermaid> graph TD A[编写测试] --> B[运行测试] B --> C{测试通过?} C -->|否| D[编写实现] D --> B C -->|是| E[重构] E --> A </mermaid> == 高级单元测试技术 == === 参数化测试 === 允许使用不同的输入参数运行相同的测试逻辑: <syntaxhighlight lang="cpp"> #include <gtest/gtest.h> class ParamTest : public testing::TestWithParam<std::tuple<int, int, int>> {}; TEST_P(ParamTest, Addition) { auto params = GetParam(); EXPECT_EQ(Add(std::get<0>(params), std::get<1>(params)), std::get<2>(params)); } INSTANTIATE_TEST_SUITE_P( AdditionTests, ParamTest, testing::Values( std::make_tuple(2, 3, 5), std::make_tuple(10, 20, 30), std::make_tuple(-2, -3, -5) ) ); </syntaxhighlight> === 模拟对象 === 当测试依赖外部资源时,可以使用模拟对象: <syntaxhighlight lang="cpp"> #include <gmock/gmock.h> class Database { public: virtual ~Database() = default; virtual int GetValue(const std::string& key) const = 0; }; class MockDatabase : public Database { public: MOCK_METHOD(int, GetValue, (const std::string& key), (const, override)); }; TEST(DatabaseTest, MockExample) { MockDatabase db; EXPECT_CALL(db, GetValue("test_key")) .WillOnce(testing::Return(42)); // 被测代码使用db.GetValue("test_key")应该返回42 } </syntaxhighlight> == 单元测试最佳实践 == * 测试名称应描述测试目的 * 每个测试用例应专注于一个行为 * 避免测试实现细节,测试行为而非实现 * 保持测试快速运行 * 测试应独立于环境 * 测试失败时应提供有用的错误信息 * 测试代码应与生产代码保持相同质量标准 == 实际案例 == 考虑一个简单的银行账户类: <syntaxhighlight lang="cpp"> class BankAccount { private: double balance; public: BankAccount() : balance(0) {} void Deposit(double amount) { if (amount > 0) balance += amount; } bool Withdraw(double amount) { if (amount > 0 && balance >= amount) { balance -= amount; return true; } return false; } double GetBalance() const { return balance; } }; </syntaxhighlight> 对应的单元测试: <syntaxhighlight lang="cpp"> TEST(BankAccountTest, InitialBalance) { BankAccount account; EXPECT_DOUBLE_EQ(account.GetBalance(), 0.0); } TEST(BankAccountTest, DepositPositive) { BankAccount account; account.Deposit(100.0); EXPECT_DOUBLE_EQ(account.GetBalance(), 100.0); } TEST(BankAccountTest, DepositNegative) { BankAccount account; account.Deposit(-50.0); EXPECT_DOUBLE_EQ(account.GetBalance(), 0.0); } TEST(BankAccountTest, WithdrawSuccess) { BankAccount account; account.Deposit(100.0); bool result = account.Withdraw(30.0); EXPECT_TRUE(result); EXPECT_DOUBLE_EQ(account.GetBalance(), 70.0); } TEST(BankAccountTest, WithdrawFailure) { BankAccount account; account.Deposit(50.0); bool result = account.Withdraw(60.0); EXPECT_FALSE(result); EXPECT_DOUBLE_EQ(account.GetBalance(), 50.0); } </syntaxhighlight> == 数学公式示例 == 在某些情况下,你可能需要验证涉及数学计算的函数。例如,测试一个计算平方根的函数: <math>\sqrt{x}</math> 的近似值可以通过牛顿迭代法计算: <math>x_{n+1} = \frac{1}{2} \left( x_n + \frac{S}{x_n} \right) </math> 对应的测试用例: <syntaxhighlight lang="cpp"> TEST(MathTest, SquareRoot) { EXPECT_NEAR(sqrt(2.0), 1.41421356, 1e-6); EXPECT_NEAR(sqrt(9.0), 3.0, 1e-6); } </syntaxhighlight> == 结论 == C++单元测试是确保代码质量的重要工具。通过使用适当的测试框架和遵循最佳实践,开发者可以创建更可靠、更易维护的代码。单元测试不仅帮助捕获错误,还能作为代码行为的文档,并促进更好的软件设计。 [[Category:编程语言]] [[Category:C++]] [[Category:C++ 调试与测试]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)