C++ 代码整洁之道:C++17 可持续软件开发模式实践 (13):构建安全体系 2.3

阅读数:45 2019 年 12 月 4 日 18:47

C++代码整洁之道:C++17可持续软件开发模式实践(13):构建安全体系 2.3

(单元测试)

内容简介
本书致力于讲述 C++ 整洁代码之道!如果你想让自己写的代码更加整洁,那么这本书适合你阅读。本书需要熟悉 C++ 语言的基本概念,才能有效的掌握其中的内容。如果你只是想从 C++ 开发开始,并且没有 C++ 语言的基础知识,你应该首先选择一个好的 C++ 入门的练习项目。此外,本书也不包含任何深奥的技巧和杂乱的知识点。我知道 C++ 有很多令人兴奋的技巧,但这些通常不是整洁代码的精神,也不是现代 C++ 的代码风格。除此之外,这本书为了帮助 C++ 程序员提高技能水平,并举例说明如何编写易于理解的、灵活的、可维护的和高效的 C++ 代码。即使你是一个经验丰富的 C++ 开发人员,这本书中也有一些值得学习的地方,我认为这些值得学习的地方能够促进你的工作。书中所提出的原则和实践可以应用于新的软件系统,有时被称为“绿地项目”,以及具有悠久历史的遗留系统,通常被称为“棕地项目”。

没有测试的“重构”不能称之为重构,它仅仅是到处移动垃圾代码。
——Corey Haines (@coreyhaines), December 20, 2013, on Twitter

单元测试是一小段代码,在特定上下文环境中,单元测试能够执行产品的一部分代码。单元测试能够在很短的时间内,展示出你的代码是否达到了预期的运行结果。如果单元测试覆盖率非常高,那么,你就可以在很短的时间内,检查正在开发的系统的所有组件是否运行正常。单元测试有许多优点:

  • 大量的调查和研究已经证明,在软件部署运行以后修复 bug 的代价,比在单元测试阶段修复 bug 的代价要高得多。
  • 单元测试能够给出关于整个代码库(已经写了单元测试的那一部分代码) 的即时反馈,如果单元测试覆盖率足够高(大约 100%),开发人员在几秒钟内就能知道代码库中的代码是否能够正常运行。
  • 单元测试让开发人员有足够的信心重构代码,而不必担心因重构而带来的错误。事实上,没有单元测试的重构是非常危险的,严格来讲,不能称之为重构。
  • 高覆盖率的单元测试,可以有效防止陷入耗时和让人手足无措的代码调试中,可以大大降低长时间使用调试器调试的问题。当然,没有人能够完全避免使用调试器调试。调试器可以用来分析细微的问题,或者找出执行失败的单元测试的原因。但是,调试器不应该是确保代码质量的关键工具。
  • 单元测试是一种可以被执行的产品文档,因为单元测试精确地展现了代码是如何被设计和使用的。可以说,单元测试是一组非常有用的示例代码。
  • 单元测试可以很容易地检测回归测试的代码,也就是说,单元测试能够很快地检查更改代码后引发的异常。
  • 单元测试可以促进实现整洁且良好的接口,可以帮助开发人员避免文件间不必要的依赖关系。可测试性的设计也是良好的可用性的设计,也就是说,如果一段代码可以很容易地与测试夹具1集成,那么,这段代码通常也可以很容易地集成到产品的代码。
    1 详见单元测试框架的 Test Fixure,如:gtest、boost.test。—译者注
  • 单元测试能够促进开发。

上述提到的最后一个优点看似是矛盾的,这里做一下解释,单元测试能够促进开发——这似乎是不可能的事情,也不合乎正常的逻辑。

毫无疑问,编写单元测试意味着成本的投入。首先,最重要的是,管理者只看到了这种成本的投入,却并不明白为什么开发人员应该为测试投入时间。特别是在项目的开始阶段,单元测试对开发速度的促进几乎是看不见的。在项目的早期阶段,当系统的复杂度较低并且大部分组件都工作得很好的时候,编写单元测试看起来只是无意义的付出。但是,时代正在改变……

当系统变得越来越庞大(超过 100 000 行代码量)且系统复杂度增加时,理解和验证系统变得越来越困难(还记得我在第 1 章描述的软件熵吗?)。通常,当不同开发团队中的许多开发人员协同开发一个庞大的系统时,他们每天都要面对其他开发者编写的代码,如果没有单元测试,这将成为一项令人沮丧的工作。我确信,团队中的每个人都知道那些愚蠢的、无休止的调试,在单步模式中一遍又一遍地调试代码,同时一次又一次地分析变量的值……这非常浪费时间!并且,这也将大大降低开发速度。

特别是在软件开发的中后期,以及在产品交付后的维护阶段,良好的单元测试会展现出它们积极的一面。在编写单元测试后的几个月或几年里,当一个组件或产品的 API 需要更改或扩展的时候,单元测试能够最大程度地节省时间。

如果单元测试覆盖率很好,那么开发人员编辑一段自己写的代码或别人写的代码,影响不会太大。良好的单元测试有助于开发人员快速理解另一个人编写的代码,即使这段代码是在三年前编写的。如果单元测试失败,通过失败的信息,能够准确知道失败的地方。开发人员可以相信,如果所有的单元测试都通过了,那么所有的函数都可以正常运行,烦人的调试就会变得不常见。调试主要用于分析那些错误现象不直观的失败的单元测试,这将是一件很有趣的事情。单元测试具有正向的促进作用,能给我们带来更快更好的结果,开发人员也将对基础代码有更大的信心,并对此感到满意。如果更改需求或加入新的特性呢?也没有问题,因为单元测试能够快速、频繁地完成产品的单元测试,并且能够保证产品的质量。

单元测试框架
C++ 的单元测试框架有很多种,例如:CppUnit、Boost.Test、CUTE、Goole Test 等。
一般而言,几个单元测试框架的集合称为 xUnit,所有遵循所谓的 xUnit 的基本设计的单元测试的框架,其结构和功能都是从 Smalltalk 的 SUnit 继承而来的。抛开实际情况不谈,本章内容没有涉及某个单元测试框架,因为本章内容适用于一般的单元测试,单元测试框架完整而详细的对比内容将超出本书的范围。进一步讲,选择一个合适的单元测试框架取决于很多因素。例如,如果以最小的工作量和最快的速度添加新的单元测试,对你来说是非常重要的,那么,最小的工作量和最快的速度将成为你选择单元测试框架的主要因素。

C++代码整洁之道:C++17可持续软件开发模式实践(13):构建安全体系 2.3

购书地址 https://item.jd.com/12599914.html?dist=jd

评论

发布