前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >测试人员代码分析5步法

测试人员代码分析5步法

作者头像
腾讯移动品质中心TMQ
发布2018-02-06 15:36:39
1.2K0
发布2018-02-06 15:36:39
举报

前言

随着测试行业的发展,测试攻城狮也越来越关注产品的源码了。在很多团队中,读懂代码的实现是做好测试的重要一步,但是读懂代码这件事非常依赖代码能力,没有什么捷径可走。笔者也是这么一步一步过来的,本着为行业添砖加瓦的精神,我总结了几条规律,希望能抛砖引玉。

理论篇

实际工作中,我们经常面临版本迭代节奏快、需求多、测试时间短、代码量大等现象,当我们决定深入理解代码实现的时候,经常会遇到以下两个问题:如何进行代码分析?优先分析哪些代码?

代码分析的关键词:5步法+风险控制+类关系

5步法操作如下:

1、选取分析对象

2、明确模块名

3、理清模块间的关系

4、确定模块间的接口

5、从接口着手去梳理代码结构关系

第一步 选取分析对象

测试周期短、代码量大,从哪里着手开始分析、或者优先分析哪些呢?

代码分析顺序的关键词:风险控制。所谓风险控制,从问题严重度和模块特点两个方面来说:

1、问题严重度:模块出现问题后,被用户感知的严重程度。按照问题严重度顺序做代码分析。比如,驱动层代码出问题会“蓝屏”,应用层出问题会“crash”、"无反应",脚本出问题,脚本挂掉,用户侧基本无感知。即蓝屏>crash>无反应>无感知,所以最优先分析的是驱动层代码,其次是应用层代码,最后才是脚本;

2、模块特点:问题严重度在同一层级,代码的分析顺序。首先,同一层级的代码,应该优先分析重要的模块,重要模块是核心功能处理、调用频繁度高的模块;其次,出现问题的模块会隐藏更多的问题,分析那些已经发现过问题的模块,可能会发现更多的问题。

第二步 明确模块名

通过查看工程文件或工程属性,明确源代码将会被编译成xxx名称的.xxx扩展名的文件。代码最终都会被编成.xxx后缀的目标文件,在开始梳理具体实现前,要明确目标文件的名称和运行方式。

第三步 理清模块间的关系

确定了模块名后,紧接着要确定多个相互作用的模块的调用关系。从当前代码所在的模块出发梳理调用关系,首先需要明确调用关系是两个以上模块之间的关系,也就是在调用过程中,存在调用方和被调用方;其次,当前代码所在模块在实际调用中,可能会调用其它模块,也可能被其它模块调用。

1、哪些模块调用了当前模块:在整个业务代码范围内搜索当前模块的模块全名,包含.xxx后缀,就能找出该模块被哪些模块调用。

2、当前模块调用了哪些模块:在该模块的工程文件中,搜索和分析会和其他模块发生调用关系的关键词,这里的关键词一般是加载函数的名字、文件后缀名等,即可找到该模块调用了哪些模块。

第四步 确定模块间的接口

在当前模块被调用和调用其他模块的语句处,即步骤三中发生调用关系的语句处,找到模块间起连接作用的接口。具体接口的形式、分类和使用方法依赖于平台和代码开发语言,确定接口的准则会有所不同,这里不赘述,大家可根据自己实际分析的代码确定接口。

第五步 从接口着手去梳理代码结构关系

从接口入手梳理代码结构关系首先要做两件事:

①查看该接口类的定义和各个方法名称,明确该接口具备什么方法。接口类一般都是抽象类,抽象类里的方法一般没有具体实现;

②找接口类的实现类,即搜索public 接口类名,找到该接口的实现类,从实现类的各个方法定义中开始分析各个方法的具体实现逻辑,这些实现过程可能包含对其他模块的调用、对其他接口/类的调用、对本接口其他方法的调用。

从接口入手开始分析代码的依据是类关系的强弱性,先简单说明UML给出的六种类关系的强弱顺序:泛化=实现>组合>聚合>关联>依赖。泛化和实现关系像是代码结构的纵向关系,我们理清实现和泛化关系,就等同于找到房子的承重墙;组合、聚合和关联更能代表代码结构的横向关系,是具体实现过程;依赖关系也是一种代码结构的横向关系,但是这种关系比较弱,即对代码的整个框架影响较小,所以分析时不建议花费太多时间。

在逐步分析确定具体实现逻辑的过程中,有以下几个关注点:

①从需求的功能出发,确定功能是否如期实现、代码中是否有分支遗漏、各种异常处理是否完备;

②从CodeReview角度出发,查找代码中的基本缺陷,如变量没有初始化、资源使用完后未释放、函数返回值出错等;

③从代码实现结构出发,确定设计的接口是否合理、多线程流程是否恰当、架构是否清晰等。

实战篇

以下将按照上文阐述的”五步法“,以Windows系统Visual Studio下C++代码为例,进行实战演练。

第一步 选择分析对象

例如分析的项目包含C++代码和Lua代码,从风险控制的角度出发,优先选择C++代码进行分析。

这时将会遇到另一个问题:模块关系是怎么样的?具体实现逻辑是怎么样的?

第二步 明确模块名

打开.vcproj工程文件,查看ConfigurationType值(2是dll文件,1是exe文件),或者VS里面查看工程属性Properties-ConfigurationType就可以看出该文件的生成文件名(xxx.xxx),dllTest.vcproj最后编译出来的二进制文件是dllTest.dll。

第三步 理清模块间的关系

1、哪些模块调用了当前模块:在整个解决方案文件(.sln)中搜索模块名,可看出哪些模块调用了该模块,dllCall\dllCall.cpp所在模块dllCall.exe(步骤二的方法获取模块名)会调用dllTest.dll。

2、当前模块调用了哪些模块:在.vcproj工程文件中搜.lib、LoadLibrary、CoCreateInstance,可以看出dllCall.exe包含shell32.lib等静态库。

dllCall.exe会通过LoadLibrary调用dllTest.dll这个动态库。

dllCall.exe会通过CoCreateInstance调用dllCom.dll等动态库。

除了通过搜索关键字的方式获取模块关系之外,还可以通过调试和depends.exe等工具来理清楚模块间的依赖关系。

第四步 确定模块间的接口

C++接口一般分为COM接口和LoadLibrary导出接口两类,其中LoadLibrary导出接口的使用方法又细分为两种:

①COM接口,CoCreateInstance的第四个参数就是接口的IID,IID_后直接跟的就是接口类的名称;

②LoadLibrary导出接口,GetProcAddress的第二个参数就是接口函数:a.该接口函数直接被使用;查找该接口函数的定义,如下add是接口函数。

b.通过该接口函数找到接口类,需要具体分析代码和接口函数,如ICacheClient是通过接口函数GetModuleName找到的实际调用的接口类ICacheClient。

第五步 从接口着手去梳理代码结构关系

上例接口ICacheClient的实现类是CCacheClient。

CCacheClient的方法和属性如下:

CCacheClient的SendGetDigFtr方法的实现分析如下:

工具篇

组合、聚合和关联关系的代码在整个工程中占比非常大,是代码分析比较耗时的过程,我们可以借助工具辅助分析,推荐代码阅读分析工具Understand。

UnderStand集成了代码编辑器、代码跟踪器和代码分析器,支持C/C++/C#, Ada, Java, FORTRAN, Delphi和Jovial等语言,并且具有强大的界面,能将分析结果以图表、图形等形式呈现给大家,如下实例图依次为Understand生成的类关系图、函数调用关系图和数据流图。

最后,那么对于我们来说,要在有限时间内完成高质量的代码分析,才能更好的适应“迭代节奏快、需求多、测试时间短、代码量大”等现状、更好的打击和消灭bug。希望以上代码分析的方法能为大家提供一些思路,能帮助大家提升一些代码分析效率。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯移动品质中心TMQ 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 理论篇
  • 工具篇
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档