代码覆盖率在谷歌中的应用|谷歌代码覆盖率系统的组成模块及其功能

2021-08-25   出处:土司阿哈  作/译者:shower、土司阿哈  

前文回顾

        上期文章《[翻译]代码覆盖率在谷歌中的应用|代码覆盖系统的现状及功能架构》介绍了谷歌的代码覆盖率测量计算系统(以下简称代码覆盖系统),主要包括该系统的开发背景,系统中覆盖率的类型和计算范围,以及系统的基础架构。本期将对该系统的每一个组成模块及其功能(如Figure3所示)作具体介绍。

模块1:代码覆盖的插桩量化工具(Coverage Instrumentation)

        谷歌的代码覆盖系统综合采用了多种成熟的外部代码覆盖函数库,配合使用内部开发的工具,以支持对多种编程语言进行代码覆盖的测量。针对每一种编程语言采用的工具具体如下:

        1.C++:gcov[1]

        2.Java:JaCoCo[2]以及内部开发的对安卓系统支持的架构

        3.Python:Coverage.py[3]

        4.Go:Go语言中有内嵌的代码覆盖率计算指令(go-cover)[4]

        5.JavaScript:Istanbul[5]及内部开发的函数库,以及用于支持它们的相关系统架构

        6.Dart:Dart-lang有内嵌的代码覆盖计算支持[6]

        7.TypeScript:重用很多用于JavaScript的系统架构和工具

        为了把上述所有函数库集成到一个系统中并且采用统一化的输出格式,我们对这些外部的函数库进行了修改,或者在系统架构的最上层进行链接整合。具体来讲,我们或者修改函数库本身使它们产生统一的以lcov为格式的输出,或者开发自定义的架构将函数库的已有输出转化为统一的lcov格式。lcov格式是基于文本的跟踪文件格式,这种格式被gcov[1]和它的前台指令lcov用来存储代码覆盖信息。

        从概念上讲,lcov不仅支持代码行覆盖(line coverage)和分支覆盖(branch coverage),它还可以模拟其它类型的代码覆盖率。在这么多可用的代码覆盖指标中,我们选择代码行覆盖作为主要的测量指标,因为它不仅和指令覆盖具有强相关性,而且易于被视觉化和被理解。我们的实践也证明了这个选择的优越性。

模块2:编译系统集成(Build System Integration)

        谷歌使用Blaze作为核心的编译系统。Blaze是Bazel编译系统[7]的内部版本,它支持对函数库的编译链接,对测试的执行,并计算整合代码覆盖率信息。我们可以通过使用Blaze的命令行界面调用对指定代码路径计算覆盖率的命令,以此触发覆盖率的计算操作。Blaze会自动处理覆盖率的计算,这种抽象计算不依赖底层函数库的具体实现。

模块3:代码覆盖自动化(Coverage Automation)

        在Blaze的基础上,谷歌的代码覆盖率系统为把代码覆盖计算集成到常规的开发流程中提供了进一步的自动化。开发人员只需要在项目定义中设置一个布尔选项(enable_coverage=true)就能轻易触发自动化的代码覆盖计算。

        在一个项目中,一旦代码覆盖率的计算被激活,这个自动系统每天都会计算一次项目级别的覆盖率,即“项目覆盖(project coverage)”。这个系统也会对所有直接改变了项目代码的变更集(也称“修改列表”)进行覆盖率计算,即“代码变更集覆盖(changelist coverage)”。具体来讲,每一个代码变更集第一次被送去代码审核前都要至少进行一次覆盖率的计算。如果在代码审核期间该变更集中的代码再次被修改,我们在将其最终提交到代码库之后,会至少重新计算一次它的覆盖率。

        所有程序员都可以在任何时候提交对变更集进行覆盖率计算的请求,即使是在代码审核过程中。他们只需要在代码审核的用户界面上点击一个按钮就可以完成这个操作,这在实际工作中是非常必要的。比如,有时候我们会在审核变更集的过程中再次对其进行重大修改,这种情况下,代码变更集的作者或者审核者会及时提交重新计算代码覆盖的请求。如果一个修改列表(变更集)同时修改了多个项目的代码,这些计算结果将被组合起来。

        这个计算覆盖率的自动化系统会对函数库的输出(lcov-格式)和每一条测试用例的执行情况进行处理,并生成一个合并的覆盖率报告。在处理过程中,系统并不会单独存储每一条lcov输出,而是对每一个文件的代码覆盖状态采用两条序列来编码存储——一条序列编码记录每一行代码是否被插桩,另一条序列记录被插桩的代码是否被测试覆盖。编码后所有的lcov原始输出都会被删除。这个简化压缩的过程是对资源的重要优化,并因此解决了可扩展化的问题。

模块4:视觉化和数据分析(Visualization and Data Analytics)

        谷歌的代码覆盖率系统对覆盖率信息采用了多种方式的视觉化:【变更集覆盖率】在谷歌的代码审核系统Critique中被视觉化;【项目覆盖率】在CodeSearch[8]和开发人员的IDE中被视觉化。最后,这个系统还为【项目覆盖率】提供了趋势图,工程师或研究人员可以通过查询这些覆盖率数据来进行数据分析。

        在Critique中,每一个受到修改列表(即变更集)影响的项目都会显示【变更集覆盖率】,并生成总结报告。如图4所示,每一行代码的表面会用颜色标记显示该代码行的覆盖情况,而每一个文件的覆盖率和所有变更集的整体覆盖率则采用数字形式的报告,如图5所示。

        4:代码审核中的代码行覆盖率可视化

        5:代码审核中综合覆盖率可视化

        CodeSearch[8]的内部版本帮助谷歌的开发人员浏览整个公司的代码仓库,它包含了超过10亿行代码。CodeSearch使文件的浏览,符号的对照查询,以及历史版本的查阅变得非常容易。人们也能很便捷地在其中读取代码行覆盖信息,如图6所示。系统通过读取处理底层数据实现这些视觉化,而这些数据来自每天的项目覆盖计算结果。并且,系统只显示那些在最后一次计算后就没有再被修改过的文件。

        6:代码查询中的覆盖率可视化

        在代码编辑器和集成开发环境(IDE)中对代码覆盖信息可视化是另一自然选择。通过使用与CodeSearch相同的数据源,我们对许多代码编辑器提供个性化的支持。例如,我们对Vim的代码可视化插件metaplugin已经对公众开源了[9]。

        除了对变更集和项目覆盖进行视觉化,我们的系统也支持趋势可视化(trend visualization)和数据分析(data analysis)。例如,通过使用预先建立的趋势可视化用户界面(UI),程序员可以跟踪并预测一个项目覆盖率在项目执行期间,甚至包括未来一段时间的变化趋势。类似的,程序员也可以通过使用Dremel查询系统[10],发出具体的查询指令来获取相同的信息。所有的覆盖数据都存储在中心数据库以供交互查询和分析。这个功能的主要用户是开发人员和研究人员,他们会对这些大批量的覆盖数据进行分析总结,了解项目的进展和变化状况,从中找出在整个开发周期中存在的漏洞,或发现在工程实践或工具开发中可以提高的地方,等等。

        本文将在第二部分介绍具体的使用场景和案例,并报告具体的数据。这一部分将在今后的文章里给大家呈现。

参考

        [1]Using the GNU Compiler Collection(GCC):Gcov.https:

        [2]JaCoCo Java Code Coverage Library.https:

        [3]Coverage.py.https:

        [4]The Go Blog-The cover story.https:

        [5]Istanbul Code Coverage.https:

        [6]Dart-Coverage.https:

        [7]Inc.,G.Bazel build system.https:

        [8]Codesearch.https:

        [9]vim-coverage.https:

        [10]Melnik,S.,Gubarev,A.,Long,J.J.,Romer,G.,Shivakumar,S.,Tolton,M.,andVassilakis,T.Dremel:Interactive analysis of web-scale datasets.In Proc.ofthe 36th Int’l Conf on Very Large Data Bases(2010),pp.330–339.

        


声明:本文为本站编辑转载,文章版权归原作者所有。文章内容为作者个人观点,本站只提供转载参考(依行业惯例严格标明出处和作译者),目的在于传递更多专业信息,普惠测试相关从业者,开源分享,推动行业交流和进步。 如涉及作品内容、版权和其它问题,请原作者及时与本站联系(QQ:1017718740),我们将第一时间进行处理。本站拥有对此声明的最终解释权!欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,与我们的编辑和其他窝友交流。
142°|1422 人阅读|0 条评论

登录 后发表评论