生活宝|商城|团购|房产|招聘|外卖|交友|微博|汽车|同城|游戏|贷款|发稿|建站|软件|客服
上海论坛

测试之道--阿里巴巴八年测试专家倾情奉献

更新于 2018-1-12 18:02:34 2161人阅读 0人回复 显示全部楼层 倒序浏览

a
0 0
  @ME:   
  • TA的每日心情
    慵懒
    6 小时前
  • 签到天数: 60 天

    连续签到: 3 天

    [LV.6]常住居民II

    发表于 2018-1-12 18:02:34 | 显示全部楼层 |阅读模式
    53快服 销量提升50%

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

    您需要 登录 才可以下载或查看,没有帐号?快速注册

    x

    摘要: 我从事测试工作将近八年了,从起初的不懂测试,怀疑测试,到相信测试,再到坚定测试,其中经历的辛酸、煎熬无法言表。在从事测试工作的这八年里,有人质疑,也有人追捧,唇枪舌剑,没完没了,貌似测试永远都是个站在舆论风口浪尖的角色。

    点击查看原文

    一、  前言
    我从事测试工作将近八年了,从起初的不懂测试,怀疑测试,到相信测试,再到坚定测试,其中经历的辛酸、煎熬无法言表。在从事测试工作的这八年里,有人质疑,也有人追捧,唇枪舌剑,没完没了,貌似测试永远都是个站在舆论风口浪尖的角色。本文乃在下之精血所作,是我对测试的高度概括,旨在帮助大家了解测试,新人可以更好地从事测试工作,老人可以进行测试探讨,交流思想。为了尽量让更多的人理解测试,本文重在述道,少说测试之术,相信看完之后,各位自有论断,功过是非留于各位看官说。
    二、  测试的万能模型
    为什么上来就谈这个?测试的模型既是我对测试认知的高度建模,也是帮助大家理解测试,理解我观点的出发点,正所谓“风,生于地,起于青萍之末”,任何事情都是有本因的,大道至简,理解了核心思想再看观点,就有了论据,这正如修炼武功,根基决定了以后武术达到的高度,否则就如“无本之木,无源之水”,虽然我言之凿凿,但大家却都不知吾之所云。
      
    佛家修炼有三个境界:看山是山,看水是水;看山不是山,看水不是水;看山还是山,看水还是水。从我对测试的经历和认知来说非常吻合,起初开始做测试的时候感觉测试工作是无聊的,枯燥的,而且并没有太大技术含量,以为这就是测试。但是随着工作阅历的增加,觉得测试越来越难,面对各种被测系统,我真的无法用一种通用的方法,或者通用工具满足所有的测试需求。于是开始拼命学习各种系统的实现,尝试去了解我的被测系统。我测试过的系统有java开发的,也有C++开发的,也有其它语言开发的,于是我对各种语言都有一定了了解,开始研究如何测试他们。随着光阴流逝,对测试认识的逐步加深,我发现所有的测试理念都是相通的,渐渐的,我悟出了万能的测试模型:y= f(x)。对,你没看错,就是我们所学的函数表达式。
    x是我们的输入,y是f(x)的输出,f(x)表示的是被测系统的功能。测试的思路就是:选择适当的x,代入f(x),得到y,跟我的预期结果y’进行对比,从而得出被测流程是pass还是fail。用图表示:
    对于测试人员来说SUT(System Under Test,被测系统)是个黑盒,测试人员一般不太会关注f(x)的具体实现逻辑,只会关注f(x)的功能。比如,假设f(x)= 2^x,程序可以用“x个2相乘”实现,也可以用“左移位”的方法实现,作为测试人员关注点只在于“有没有正确实现需求?”,“功能满足后性能如何?有没有安全问题?”,关注点不在“怎么实现”,而在“实现的怎么样”上面(这也是测试思维跟开发思维的本质区别)。是故,弄懂业务,理解产品需求是测试的前提。
    也许有人会问,没那么简单吧,系统那么复杂,仅仅一个y= f(x),怎么能全部归纳?你这里只有一个请求,一个响应,系统那是多复杂啊,数据库,缓存,异步消息,日志等。这里得强调的是,x,y表示的绝不仅仅是request和response,而是广义的输入和输出,什么区别?request和response只是输入输出的一种,对于SUT来说,只要是读的数据都算输入,比如:用户登陆的功能,当我填入一个用户名进行登录时,我的输入除了在页面上填入的“用户名”和“密码”,DB中也必须有这条用户记录(当然用户不存在也是一种测试场景),所以DB中的这条用户记录也算输入,甚至如果登录系统处理过程中去查询安全系统,安全系统返回的“用户安全策略”也算输入。所以,这里的输入是广义的输入,包含了用户页面填入的“用户名/密码”,DB中的“用户记录”,安全返回的“用户安全策略”等。同理,输出也是广义的,包括“DB的写”,“对其它系统的请求”,“打印的日志”,“对缓存的put”,“发出的异步消息”等。于是我们的测试万能公式可以进化成下面的样子:y1,y2,y3,…,yn= f(x1,x2,x3,…,xn)。我们测试工作其实就是确定每一个x的取值范围,然后选用合适的x1到xn的组合数据(一组数据其实就是一个测试用例),代入f,然后将得到的y1…yn跟预期的y1’…yn’进行比较,从而判断被测场景的正确性。用图表示:
    所以,一个合格的测试,必须理清“SUT的功能”,“SUT的所有输入”,“每一个输入的取值范围”,“SUT的所有输出”,“根据功能推出每一个输出的预期值”。
    这里还要强调的一点是,这里的SUT是很有讲究的,在我看来除了静态走读代码的方式算是白盒测试外,其它的一切测试都算黑盒,只是这个“盒子”的大小不同而已。单元测试中“盒子”比较小,就是一个或者若干个方法;接口测试的“盒子”就会扩大到应用级别;集成测试的“盒子”就会扩大到系统级别。
    弄懂了测试的模型,就可以开始剖析测试各个的关键点。
    三、  测试的目的
    测试的目的就是规避Bug。为什么用“规避”而不是“找”?因为对于所有的测试用例来说,并不是每一条都能测出Bug,对于没能测出Bug的用例执行,你能说测试工作没有价值吗?显然不能,对于测试人员来说,在未执行测试之前,假设的前提是所有的被测流程都处于未知状态,只有执行完对应的测试用例这个流程状态才变得可知——pass或者fail,对于fail的测试用例我们是找到了Bug,而对于pass的测试用例我们没有也不可能找到Bug,所以不管pass还是fail,测试执行工作都是有价值的,这里只能用“规避Bug”来精确地阐述测试工作的目的。
    四、  测试的步骤
    再来看一下测试的模型图:
    如前面所述,测试工作其实就是确定每一个x的取值范围,然后选用合适的x1到xn的组合数据(一组数据其实就是一个测试用例),代入f,然后将得到的y1…yn跟预期的y1’…yn’进行比较,从而判断被测场景的正确性。由此可以总结出,测试工作步骤就是:
    • “确定x1至xn的组合数据”
    • “将每组数据传入SUT”
    • “根据需求确定每组输入数据输入后产生的预期输出结果y1’至yn’”
    • “将预期结果和实际结果y1,y2,…,yn进行比对,从而得出结论”
    五、  测试的难点
    对于上面四步,第3点和第4点相对容易,测试的主要难点在于第1点和第2点:
    1.      如何找齐所有的x和y?
    想要找齐所有的x和y,就必须要求你对系统非常熟悉,对流程非常熟悉。系统依赖如何?流程调用,系统如何处理、交互?产生哪些反应?典型的输入有:调用请求,读DB数据,读缓存数据,被依赖系统的返回数据,收到的异步消息等;典型的输出有:写DB,写缓存,写日志,调用依赖系统的请求,发出的异步消息等。所以这个需要你对你的被测系统和流程必须非常非常的熟悉。
    2.      如何确定合适的x1至xn的组合?
    首先,你要熟悉每个x的可能取值,除了正常值,还有异常值,这个对测试工程师的要求非常高。为了清楚所有x的可能取值:
    • 不仅需要,你对业务、业务数据非常非常的熟悉。注意,这里我把“业务”和“业务数据”分开,指的是两个不同的东西。“业务”指的是产品提供的功能,比如:登录可以用账密登录,也可以用手机扫码登录。“业务数据”指的是产品在线上日以继夜的运行后产生的数据,如,注册功能,有通过淘宝注册的淘宝用户,也有通过支付宝注册的支付宝用户,甚至还有数据打通从其它地方同步过来的其它用户数据,你要对这些个业务数据非常熟悉。
    • 还需要,你要对系统间依赖的接口非常熟悉。这个主要是为了弄清楚你的SUT对依赖系统的调用,哪些调用请求的传参是合法的?哪些是不合法的?依赖方会传回给你哪些可能的数据或者响应,最好有规范的接口文档(可惜现在奇缺)。
    • 还需要,你对其它的输入方式的数据类型有比较深刻的认识。针对我负责的系统,主要是前面两个方面,当然根据不同的系统情况也有所不同,这个得具体问题具体分析。
    其次,当所有的x可能取值确定以后,这里就会利用专业的测试用例设计方法,对x1至xn的组合进行设计。设计方法有:等价类,边界值,因果图,判定表,正交法等等,这些在很多的软件测试书中都有详细的介绍,在此不作细表,有兴趣的可以自行查阅。
    3.      x1至xn如何传入SUT?
    这个用一个词来精准形容就是“驱动”,如何驱动你的测试流程?其实这个很体现测试工程师的水平。如果你用的是手工测试,那肯定得搭建测试环境,必须让你的SUT运行起来,然后预置各种数据,调用你的流程。如果你是自动化测试,这里其实是有两种方式:
    • 部署被测系统,模拟客户端发送请求驱动;
    • 直接依赖被测系统代码,用本地代码调用的方式驱动。
      总体来说,“驱动”的方式就是两种,跟语言无关,各种语言通用:
    • 代码驱动。这个没什么好说的,就是把你SUT的代码直接依赖过来,通过代码直接调用的方式进行驱动。
    • 协议驱动。这个也包含广义上的一些RPC调用,主要有http,https,ftp,telnet,hsf,dubbo等。
    六、  测试系统理念的提出
    如前面所述,测试工作的步骤就是:
    • 确定x1至xn的组合数据
    • 将每组数据传入SUT
    • 根据需求确定每组输入数据输入后产生的预期输出结果y1’至yn’
    • 将预期结果和实际结果y1,y2,…,yn进行比对,从而得出结论
    我们对上述步骤的产出进行分析,1、3两点产出的是“数据”,2、4两点产出的是“逻辑”。第4点的逻辑非常固定,就是预期输出结果和实际输出结果的比对逻辑,而第2点的“驱动”逻辑虽然有代码驱动和协议驱动,而且协议驱动也有很多种,但是因为涉及到的是接口和协议,相对还是比较固定的,不容易发生变化,非常适合将2、4做成应用。我们想象一下,如果有一个测试系统,能根据传给它的数据,完成对各种SUT的测试,那岂不是测试工程师只要产出数据(测试用例)就行了。思路完全可行,因为测试用例本质上就是一个“描述,”一个“用什么样的数据,调用什么样的流程,预期会产生什么样的结果”的描述。这种描述可以是汉语,也可以是英文,也可以是xml格式,又或者是脚本,只要能描述清楚这种语义即可,只不过我们肯定需要对这种描述制定一些格式规范,保证测试系统能够识别这种描述。这样我们的测试系统就可以集用例管理、测试执行、Bug提交、测试报告于一身,成为测试中台(不知道这个用词对不对)的完美转身。我大胆画出这种测试系统的架构示意图:
    目前我正在这个方面做一些研究,也有一些实质性的产出(驱动模块和用例管理模块),但还待琢磨完善,如果有人有兴趣的也欢迎一起探讨。
          



    您需要登录后才可以回帖 登录 | 快速注册

    本版积分规则

    品牌广播台 更多>>
    便民工具
    返回顶部快速回复返回列表联系客服手机访问
    关于我们 | 联系我们 | 广告服务 | 网站导航 | 诚聘英才 | 友情链接 | 免责申明 |  帮助中心 | 手机访问 | 排行榜 | 小黑屋 | 设首页 | 加收藏
    © 2011-2017 上海论坛 版权所有 沪ICP备11017971号-7    在线客服 举报 郑重声明:本站只提供网上自由交流讨论,所有个人言论并不代表本站立场
    快速回复 返回顶部 返回列表