犯罪心理学还能用于挖掘代码风险?
挖掘出来的东西是什么?
挖掘出来的东东长什么样子?
挖掘出来能用来做什么?
具体怎么样挖掘呢?
这是本文的主要探讨的内容.
在大型的项目中, 代码和模块的复杂度在很大程度上决定了测试任务的时间, 在项目快速迭代而测试时间比较短的情况下, 怎么样高效的完成测试并且保证测试质量? 如果我们能找到这些经常出问题还有潜在可能出问题的代码和功能区域, 我们的测试就能更高效.
地理罪犯分析调查法基于了这样一个原则:罪犯的老窝往往就在他/她作案地点的边界之内.那么,软件测试是否有这样的属性呢? 犯罪分析心理学能够指导我们测试么? 是的, 本文介绍的就是如何从代码本身挖掘出代码的问题从而指导测试的一种思路和方法.
如果我们把代码当成犯罪现场, 我们测试中所发现的问题和缺陷有什么地域属性(此地域指的是代码和功能区域) 么? 很多问题是不是会有相似的属性,是否某些文件和功能会经常出现问题. 我们能否用某种方式定位出这样的热点区域呢?答案是可以的.
那么我们是否可以用历史数据挖掘出代码本身的问题么? 事实上,我们从版本控制工具,bug数据信息,或者其他历史信息里面能找到很多有用的信息,文章后面会讲述如何为代码创造地理呈现。区域和建筑物映射代码的结构,如包或类。代码属性(如代码行数或方法数量)决定区域和建筑物的尺寸. 再结合代码版本工具既能呈现出代码高风险区域即代码热区. 再结合代码和功能之间的对应关系,就可以找到需要重点测试的功能区域(高风险的代码对应的功能模块), 从而提高测试效率, 这和精准测试的目的是一样的.
代码热区指的是被频繁改动的代码文件, 这个改动有可能是因为代码复杂度过高或者代码耦合性太强而造成新增功能都需要改动这些代码文件, 也有可能仅仅是因为代码实现的有问题需要频繁改动来修复bug
下图是几种已有工具展示的热区:
此工具支持缩放
其实展现形式并不是最主要的, 我们关注的是用代码热区能做什么.
如前言里面讲的, 精准测试的主要目的是在测试之前缩小测试的范围, 从而提高测试的效率,而如果我们能通过某种方式从历史数据中找到容易出风险的代码区域也就是所谓的代码热区,这样也可以锁定重点测试的区域,从而达到提高测试效率的目的。
从版本控制工具, 不仅能过滤出代码风险, 还能得到代码耦合度和代码复杂度关系.
对于开发人员,代码热区能提供十分有用的信息,我们可以通过代码热区再加上代码复杂度,代码耦合度等信息来衡量代码的架构和质量, 有效的指导软件代码重构。
对于测试人员, 不同的测试阶段的使用方式稍微有些不同, 具体可参照下面的表格(最后一部分也会进一步探讨怎么使用):
要找到代码热区进行测试,我们需要如下步骤:
具体要怎么做可参考下面的步骤:
Windows: download link
OSX/Linux: download link
安装完后请将执行路径加到系统变量path
安装完后请将路径加到系统变量path
https://tortoisesvn.net/downloads.zh.html
安装完后请将路径加到系统变量path
如果是git的话请安装对应的工具
https://s3.amazonaws.com/CodeMaatDistro/scripts0.4.zip
https://s3.amazonaws.com/CodeMaatDistro/sample0.2.zip
svn log -v -r {yyyymmdd}:{yyyymmdd} --xml > <svnLogFile >
例子:
svn log -v -r {20160227}:HEAD --xml > test.log
svn log -v -r {20160127}: {20160227} --xml > test.log
2. 用code maat分析总结svn log
maat -l <svnLogFile> -c svn -a revisions > <code_freqs.csv>
可以用下面的命令打印测试下
maat -l <svnLogFile>-c svn -a summary
例子:
maat -l test.log -c svn -a summary
maat -l test.log -c svn -a revisions > test_freqs.csv
注意:
需要打开结果文件把前面的三行删掉(打印的命令行)
另外svn log 打印出来的结果是在svn trunk的相对路径, 如果工作目录不是svn trunk的根路径, 需要修改文件里面代码的路径
/Test_proj/trunk/test/src/features/Log/log.cpp,94
/Test_proj/trunk/test/src/features/LogMgr/logMgr.cpp,94
/Test_proj/trunk/test/src/features/test/test.cc,75
替换成下面这样 (当前工作目录为device), 因为cloc 得出的文件路径是工作路径的相对路径, 要保持两者一致才可以
Log/log.cpp,94
LogMgr/logMgr.cpp,94
test/test.cc,75
3. 用cloc 分析文件大小
cloc-1.64.exe ./ --unix--by-file --csv --quiet --report-file=<code_lines.csv>
例子:
cloc-1.64.exe ./ --unix--by-file --csv --quiet --report-file=test_lines.csv
4. 把前面结果merge生成json 文件
python csv_as_enclosure_json.py --structure <code_lines.csv>--weights <code_freqs.csv > > <jsonFile>
备注:
可以先用merge试一下结果是否正确:
Python merge_comp_freqs.py <code_freqs.csv ><code_lines.csv>
例子:
python merge_comp_freqs.py test_freqs.csv test_lines.csv
python csv_as_enclosure_json.py --structure test_lines.csv --weightstest_freqs.csv > test.json
5.热点可视化
在sample/hibernate 目录中:
把hib_hotspot_proto.json内容替换成上一步生成的json文件
运行下面命令
prompt> python -m SimpleHTTPServer 8888 |
---|
然后浏览器打开下面链接,即可看到结果
http://localhost:8888/hibzoomable.html
备注:
也可以自己建立自己的项目目录, 具体格式可参考 hibernate 里面的hibzoomable.html
效果:
Hibernate开源项目全景图(支持鼠标缩放):
下面图为上面全景图的局部放大
在上图中(hibernate项目热区), 颜色越红, 表示代码区域被改动次数越多, 也即越有风险, 圆圈的大小表示代码文件的大小(行数),
在上文中展示的代码热区只包含两个维度: 代码大小, 代码改动次数.
在每个产品或者项目阶段, 我们可以加入自己的维度来定义或者进一步过滤代码热区来得到自己想要的结果.
例如: 有的代码文件频繁被改动可能并不真的是因为修复bug引起的, 可能会是因为新需求带来的改动,在回归测试阶段, 我们更关注这部分代码热区和高风险功能模块,所以基于上面得到的热区,我们可以再加入进一步的过滤,除了文件改动次数, 我们可以加入bug过滤来得到因为bug改动的代码热区.
如果能进一步加入bug类型或者优先级的过滤, 我们就可以提前预测到某种类型缺陷或者优先级比较高的bug过滤出来的高风险区域. 这将更有效的指导测试.
另外, 我们仅仅通过版本控制工具得到的改动次数定义的代码热区也可能并不是真的有风险的代码. 这时候我们可以通过文件的其它信息(例如, 文件的名字)来判断过滤.
代码版本控制工具本身也可以提供更多的信息:例如, 使用版本控制信息做时空耦合分析。如果两个代码文件在同一时间发生改变,这意味着文件之间是物理耦合的, 版本控制信息也可以用于挖掘知识的所有者和组件的所有权等等. 有兴趣的读者可以进一步探索下.