测试覆盖率和代码质量是少数两个用于分析、跟踪和度量IT项目有效性的度量标准。
测试覆盖率和代码质量在某种程度上是相互关联的,很少有其他指标是这样的。例如,我们度量代码质量的方法之一是通过查看相应的测试覆盖率。然而问题隐藏在使用测试覆盖率指标来度量代码质量的有效性上。
所以在这篇文章中,我们将带着批判的眼光来看待这个实践。我们将通过回顾关于使用测试覆盖率度量代码质量的普遍接受的观点,以及您如何应用一个适合您的情况的解决方案来做到这一点。
1.房间里的大象——测试覆盖率
让我们首先解决这个问题——即测试覆盖率。
“多少测试覆盖率是足够的?”
足够的测试覆盖率有助于提高您捕获所有关键/高优先级bug的机会。这不仅仅是一个您祖母讲的故事,实际上是一个非常可靠的标准来建立对您的IT系统的代码质量的信心。
然而,业内关于测试覆盖率的主要分歧似乎集中在“多少是足够的?”
理论各不相同——从60%到80%甚至100%。每个支持者都有一个合理的理由来解释为什么他们认为一定的测试覆盖率是足够的还是不够的。
似乎没有人讨论的一件事是:您根据什么来度量测试覆盖率?
不要误解我——每个人都有一个传统上被接受的度量测试覆盖率的基础——被测试软件中的代码行数。
这是正确的方法吗?这正是我们今天要回答的问题。
2.根据代码行度量测试覆盖率
这是怎么做到的呢?你只需要:
(A)你正在测试的软件的总代码行数,以及
(B)所有测试用例当前执行的代码行数
找到(B除以A)乘以100——这将是您的测试覆盖率%。
例如,
如果系统组件中的代码行总数为1000,并且所有现有测试用例中实际执行的行数为650,那么您的测试覆盖率为:
(650 / 1000) * 100 = 65%
当以执行的代码行数来度量时,通常被接受的“足够的”测试覆盖率是什么?对于关键系统,共识徘徊在80%或者更高(关键系统的定义可能因行业、地理位置、用户基础等而异)。
重要的问题是:这个度量标准是否有效?
嗯,这是一个难题。我搜索了互联网论坛寻找答案,发现一般来说,人们认为80%就足够了。然后,还有一个问题是,您是否使用了好的测试,而不是那些对覆盖率没有真正用处的测试。
好的测试是什么样的?
这并不难回答。一个好的测试应该跟踪需求的实现。正常路径和异常路径的用例都是很好的测试。
那么,您如何确保您是用好的测试来提高测试覆盖率呢?
在回答这个问题之前,让我们先看一个更重要的问题。
3.您真正应该根据什么来衡量代码质量呢?
测试覆盖率-当然。但是您如何真正度量测试覆盖率呢?
流行的答案:由测试用例执行的代码行数。
正确答案:嗯,这就是有趣的地方。
通过执行的代码行数来度量测试覆盖率
虽然传统上开发人员、测试人员和项目经理都倾向于使用这种方法,但是我一直在质疑使用这种方法来度量覆盖率的有效性。
为什么?正如这个论坛帖子告诉你的,确保100%的代码行覆盖率并不能真正得到高质量的产品。
那么是什么呢?
我之前说过,
良好的测试用例和
足够的测试覆盖率
为了实现这两个目标,您需要以批判的眼光看待您的参考点。
4.提高测试库中良好测试用例的比例
一个好的测试用例跟踪一个需求(包括正常和异常路径)到实现。为了确保您主要拥有良好的测试用例,您所要做的就是建立需求的可跟踪性。
我的团队通过清晰地规划测试场景来覆盖发布、项目、迭代、sprint范围内的所有需求,从而实现项目中的可跟踪性。通过建立需求的可追溯性,我知道——在任何给定的时间点——需求的测试覆盖率。
在敏捷项目中,假定您只关注下一个即时版本的需求,如果您使用基本的跟踪矩阵,那么通过需求实现100%的测试覆盖率应该是相当简单的。
如果您只测试需求,那么您的测试库中应该只有良好的测试用例。
现在进入下一个挑战——足够的测试覆盖率。
好吧,我开始这一部分的时候并没有告诉你正确的答案是由测试用例执行的代码行数。
“如果你确保测试用例100%覆盖了你的需求,那么你就拥有了所有你需要的测试用例。”
我为什么要那么做?
因为我不相信这是衡量代码质量的正确方法。如果你还在想“为什么?”在你的嘴唇上,所以我要试着回答这个问题。
5.如何用测试覆盖率来度量代码质量?
需求可跟踪性为您提供了一种可靠的方法来构建良好的测试用例。让我们扩展一下,思考一下为什么会这样。
如果您只编写可以追溯到需求的测试用例,那么您就有效地消除了任何冗余的、不必要的测试用例。这样可以提高团队休息的效率。
现在,如果你把它转过来,你会得到这样的结果:如果你确保100%的需求被测试用例覆盖,那么你就有了所有你需要的测试用例。
很有趣,对吧?
那么,您如何确保您有100%准确的需求呢?如果一些需求是不正确的,或者遗漏了呢?
就像他们说的,“一个建立在糟糕需求上的高质量产品,是一个低质量的产品。”
然后重点转移到确保您拥有高质量的用户描述,这些描述涵盖了所有功能性和非功能性需求。在internet上进行粗略的搜索将告诉您需要什么来确保充分有效地捕获所有需求。
6.测试覆盖在测试驱动开发TDD的世界中
让我们考虑一下我是如何运行我的敏捷项目的(例如一周的sprint)。
冲刺-第一天
我的scrum团队利用规划会议来筛选待办事项列表中最重要的x个故事。每一个故事都已经被详细阐述,并为规划会议(通过正在进行的backlog梳理会议)做好了准备。Scrum测试人员拿起新创建的sprint backlog,规划出他们希望用测试用例覆盖的所有测试场景。然后,这些场景被移交给已经在努力编写代码的开发人员。
冲刺-第2天
到目前为止,scrum开发人员已经在开发计划和启动方面取得了一些初步进展,并且有机会与BA和测试人员一起了解sprint的需求和测试场景。测试人员已经完成了对新的测试用例的脚本编写,或者从一个用例存储库中复制现有的测试用例,以覆盖所有的测试场景。他们还确定了正常和异常场景,并优先考虑这些场景。最后,他们将测试用例映射回源需求,建立可跟踪性。至此,测试人员知道当前sprint的所有需求是否已经被测试用例覆盖了。
冲刺——最后一天
Scrum开发人员使用了测试场景和详细的测试用例来指导他们的编码工作,并使用这些测试用例对代码进行了单元测试。当他们部署到一个集成的测试环境进行端到端功能测试时,大多数容易发现的错误已经被发现了。Scrum测试人员也开始使用这些测试用例来执行端到端的测试,并帮助识别那些阻止故事在sprint中交付的高/关键bug。当我们进行演示和回顾时,通常所有重要的bug都会被修复,其他未解决的bug会被优先考虑,以便在必要时进行后续的解决(我们总是在发行版的最后用一个峰值清除大多数这些“其他”bug)。
如您所见,当我们到达Sprint结束时,我的团队有一个能保证充分覆盖所有需求的测试,而且我们的测试符合标准发布(如:没有严重缺陷,100%执行测试用例,测试通过了95%)。
通过测试驱动的开发,这是可以实现的。如果你能够在每个Sprint中演示一个有效的、几乎没有bug的产品,并在此基础上清除这些bug,以修复剩下的不太合适的bug,那么我的经验告诉我,现在是发布产品的好时机。
7.那么,应该根据什么来衡量代码质量呢?
我的回答是:需求覆盖率和执行的代码行数。
为什么?坦白地说,我相信确保100%的需求覆盖率是足够的。毕竟,有了敏捷,你应该一直只处理发布的高优先级需求,从而减少浪费——精力、时间和金钱。
然而,人类并不是完美的。糟糕的需求可能会潜入您的范围。好的需求可能会被遗漏。您可能直到项目后期才会发现这一点。我们不能保证100%的准确性。
另一方面,我发现通过执行的代码行来检查测试覆盖率有助于在表面上判断代码质量。例如,如果您的测试达到了100%的需求覆盖率,并且通过了发布的所有退出标准,但是却发现您的测试只覆盖了65%的代码,这是为什么呢?
极端的例子——我同意。但这是可能的。它可能是低质量的需求和浪费的编码工作的组合。
遇到开发人员编写了太多不必要的代码行数的项目是很常见的。原因可能有很多,而且有些是合理的,但是我经常发现“过多的代码”对于我的客户的许多项目来说是一个问题。
编码工作偏离了需求,开发人员花费宝贵的资源编写不必要的代码行。
那么,如果一个开发人员严格遵循约定的范围,那么100%的代码都将被测试覆盖,这是真的吗?不一定。这又一次归结于对开发人员编写有效代码的指导不足。只编写交付需求所需的代码。即使这样,也有可能出现100%覆盖率无法实现或没有必要的情况。
因此,我们的目标不应该是实现100%的代码覆盖率——或者任何类似的具体数字。尽管当与100%的需求覆盖率相结合时,您应该能够发现代码覆盖率在缺省情况下徘徊在80-90之间。
8.我们学到了什么?
代码质量是每个人的首要任务。在一个资源成本增加和交付预算紧缩的时代,度量和跟踪代码质量以更好地了解您的团队的效率以及他们可以在哪里改进是很有必要的。
您应该使用您所掌握的每一种工具来实现您的目标代码质量指标。根据代码的总行数跟踪执行的代码行数是一种选择。但是这并不能帮助您确定足够的测试覆盖率,或者实际的代码质量。
您应该依靠互补的、有时更强大的方法来度量代码质量和测试覆盖率。您可以通过在您的测试中考虑需求覆盖率来轻松地实现这一点,这可以直接导致更好的代码质量——立即!