测试人员代码分析5步法

前言

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

理论篇

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

代码分析的关键词: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。希望以上代码分析的方法能为大家提供一些思路,能帮助大家提升一些代码分析效率。

原文发布于微信公众号 - 腾讯移动品质中心TMQ(gh_2052d3e8c27d)

原文发表时间:2016-09-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏鸿的学习笔记

Actor模型速览

Actor的核心在于发送消息和接受消息。每一个Actor系统之间的联络都依靠消息的传递,假设现在有两个Actor系统A和B,A会向B发送了一条消息打招呼,或者是...

733
来自专栏Fundebug

2020年如何写一个现代的JavaScript库

我写过一些开源项目,在开源方面有一些经验,最近开到了阮老师的微博,深有感触,现在一个开源项目涉及的东西确实挺多的,特别是对于新手来说非常不友好

1805
来自专栏芋道源码1024

从客户端的角度设计后端的接口

2.请求Path,http://www.online.com/api/ [path]

1593
来自专栏州的先生

Python并发:多线程与多进程

2172
来自专栏阮一峰的网络日志

处理Apache日志的Bash脚本

去年一年,我写了将近100篇网络日志。 现在这一年结束了,我要统计"访问量排名",看看哪些文章最受欢迎。(隆重预告:本文结尾处将揭晓前5名。) ? 以往,我用的...

3625
来自专栏落影的专栏

iOS电商类APP的研发

前言 本文是研发一个在线超市的电商类APP过程中,对架构的整理。 ? 功能: 1、浏览商品、购买商品、切换商店; 2、查看订单、订单投诉、意见反馈; 3、...

73910
来自专栏黑白安全

PHP代码审计入门之路

虽然市面上的代码审计的文章已经一大把了,但是还是决定重复造轮子,打算作为一个系列来写的,近年越来越多的安全研究人员投入到php应用的漏洞挖掘,相对应的代码安全问...

972
来自专栏Danny的专栏

【项目实战】——Java实现伪静态——urlrewrite

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

1724
来自专栏py+selenium

py+selenium遇见IE,元素只有name属性【神奇解决】

IE8的问题:IE8不支持getElementByName,而属性中又没有ID,定位难度较大。

3731
来自专栏Python爬虫与数据挖掘

网络爬虫过程中5种网页去重方法简要介绍

一般的,我们想抓取一个网站所有的URL,首先通过起始URL,之后通过网络爬虫提取出该网页中所有的URL链接,之后再对提取出来的每个URL进行爬取,提取出...

771

扫码关注云+社区

领取腾讯云代金券