首页 > 代码库 > How Tencent Tests Software
How Tencent Tests Software
<style></style>
How Tencent Tests Software
前言
这是一篇一年前的旧文,搬迁过来
标题向james whittaker的《谷歌如何测试软件》(How Google Tests Software)致敬,此君的”Test Is Dead”名句以及另一本《探索性测试》都让我收益良多,也推荐大家看下
我在企鹅的测试体验以及思考
在腾讯工作了快三年,分别在财付通和微信支付部门做系统测试工作,对测试体验和其中的思考做下总结
财付通的测试流程
由于支付业务的高风险性,财付通是流程比其他兄弟部门重一些,感觉整体流程上和目前杭研的流程较类似,区别在于杭研这边更注重输出、统计和分析。
基本一个项目的流程是:
需求->设计->编码->提测->测试->多级内部环境验证->正式发布上线
项目中的角色:
- 产品: 需求方,有时兼PM
- PM: 跟进项目,协调资源,指定总体计划等
- 开发:编码,写文档
- 测试:测试工作的执行人
- QA: 并不隶属于项目,负责流程制定以及问题版本或线上问题跟进,比如一个测试单我记录了开发这边有自测不充分的问题,QA就介入了
测试阶段要做的事:
需求分析->工作量评估(中型以上项目)->用例编写->用例执行->稳定性测试(新模块)->性能测试(有性能需求的话)->风险评审(有资金风险的项目)->发布评审(大系统上线或者会对线上造成影响的情况,如系统升级)
说明
- 工作量评估: 一般1,2天的小需求直接在平台上标记下,中型以上项目需要拉有相关经验的2,3名测试同事一起评审
- 稳定性测试: 采用valgrind和长时间发送请求来查看运行是否正常,是否有内存泄漏
- 风险评审: 需要拉老大来评审风险点,方案经常被挑战,逻辑也可能因此要修改
- 发布评审: 运维会要求提供发布以及回退的方案,会提加灰度开关的需求,会提运维部署和监控的需求,逻辑也可能因此要修改
- 因为风险评审和发布评审的结果会对项目是否能顺利上线造成影响,所以一般放在第一轮测试完成时,第二轮基本上是bug fix以及根据评审结果的修改
- 测试输出为测试报告以及各种评审纪要
- 中型以上项目在测试阶段测试会发日报,说明测试进度,问题,bug等情况
测试人员除了测试任务外,还需要推动各种评审的进行,一般默认测试为风险评审和发布评审的发起人,这是苦差
由于业务繁多但人少(对比下支付宝),大家都忙得要死,实际流程执行也会有不合规的情况:
- 需求方案有时就是一句或者产品频繁变更需求
- 文档不完善或者与实现不相符
- 开发自测不充分
所以额外的工作量在于弥合开发和产品的对需求的理解,督促开发提高版本质量。另外所有改动都要走这样的流程,包括任意细小的改动,有人说这样谨慎有人说这样流程显得太重。
微信支付的测试流程
以前,微信的后台基本上都是开发自测的,微信的测试基本上都是测客户端的,后来微信支付接手后台服务后,流程和在财付通相比,轻了很多(应该说是没什么严格的流程):
- 开发了承担更多的责任,简单的特性由开发自己开发,自测自发
- 大版本和高风险版本才由测试介入,主要精力度集中在用例编写和用例执行,会议和杂事变少
- 测试和测试开发搭建自动化平台进行持续集成批跑和线上监控,为开发发布验证提供验证用例集
开发之所以能够自测自发,并不是他们发上了线的代码没有bug,而是因为微信底层框架支持请求按机器路由,按号段灰度等特性,开发一般先灰度一些量,然后观察日志,没问题就继续放量,有问题就回退,改了代码继续发。有一个强大的框架的好处在于开发不用去写一些底层代码,而那部分是很容易犯错的,同时能够自动生成测试代码,对于当时我的测试工作也有很大的帮助。
测试人员在流程中不是必须环节了,可以认为测试的地位没落了,从另一个角度看测试也自由了,以前排满了测试任务,现在分担了一部分在开发这边,有空档期可以思考下人生,做做自动化和其他平台的建设。值得担忧的是一些高风险的特性绕过了测试的监管,哪些特性必须由测试人员的测试需要制定下来。我的意见(也不知道有没被采纳)是由开发做单测后,由测试来判断哪些可以直接扔上线,哪些扔到测试环境进一步蹂躏,否则开发自己决定这个特性自测自发,代码质量较高,因为测试会测所以我就不怎么去测了,提测给测试的质量很渣,想想我都醉了。
那时候流程真乱,但发布真快,7x24小时都可以发版本,每天上线10个版本都没有问题,搞春节微信红包那时也是这样,但是没出什么事(其实是出了事之后大家修复的很快)。
测试用例
在我做新人的时候,没有文档告诉我们如何写用例(他们根本就不注重文档~),导师只是告诉我如何去思考,如何去判断,然后让我按自己和别人能理解的方式去记录。所以不同人按照不同的理解和不同的标准去写,用例放在测试报告里,形式也不太统一,一段时间统一用testlink保存测试用例,但是大家都觉得好难用~~后来一些人该用excel的用excel,用mind的工具继续用mind。这2种我都有用,数据类和后台测试我还是用excel,因为要保存很多结果和日志信息,web和客户端用mind写就好了,逻辑清晰还可以少写很多字。
文档和需求说明重要么?当然重要,但是需求反复变化、文档可能没有或是过时的时候不代表我们就干不了活了。很多的时候写测试用例是根据代码来编写,同时也需要一种叫脑补的能力,根据代码梳理一遍流程,然后和需求进行比对,和开发进行确认,经常会发现需求单上的某个地方开发漏实现了,然后让产品去屌他。
根据代码来写测试用例,估计会被人吐槽说被开发的思路牵着鼻子走,但测试对需求的了解一般是不及开发的,尤其是一些新需求,就像去了一个人生地不熟的地方找路,看到个目光凶恶的老大娘站在路边,她也许不是好人,但我还能靠谁啊~~先从开发的代码着手,逐渐进行测试,随着测试过程的进行,对模块和系统的了解逐步深入了,这时你可以抛开老大娘自己去探路了。一般不一开始就构建充分的测试用例(项目一般时间很紧,搞了几天还没弄明白,你自己都会很焦躁)而是在测试过程中不断补充和细化。一般第一版测试用例只写个标题什么的,执行步骤和结果判断就回家边看电影边写好了,最终经过不断修正增补,也许会和第一版有很大的出入,但不重要,只要先达到干活的状态,那就开搞吧,头脑无法理解的,就靠身体去体会好了。
测试活动是个制定策略筛减用例的过程,通过等价类划分来将无穷输入变为可数个,将线上集群的测试用单机来替代,以单进程或两个进程的结果来推断多进程的,但是实际中的以小见大未必足够充分。目前的测试用例往往会采用直接用例和通用用例相结合的方式来做验证,比如一个支付接口,如何处理订单如何扣款是与支付接口逻辑相关的直接用例,而在网页上进行支付和在手机上进行支付是否能看作一样的?程序员总是很懒的,测试人员也不例外,很多悲剧就发生在我原来以为只要这样就好了然后偷懒了,而没想到结果和想的不一样,擦,失算了。为了避免类似的犯错,会强制给出一份通用用例清单,自动化通用用例集也在不断建设完善中。
说到自动化。大家都会说做过自动化测试,而自动化的用例生成,自动化用的例执行,自动化的结果判断,我们所说的自动化测试在这几点中到底做到了哪几点。以前我想象有一套自动化测试工具,点一下按钮就生成用例,然后执行,最后吐出结果,在等待执行的这段时间,测试可以去喝杯咖啡轻松一下。实践中,最容易做的是自动化用例的执行,自动化框架提供了智能的调用方式,通过代码对协议进行封装,使得发送请求变得容易。自动化用例生成部分,只能一定程度上简化用例编写(比如非法字符填充),但没有办法代替人去分析需求和写测试用例。自动化的结果判断,在简单的层面,判断请求返回是否成功是较容易做的,但很多时候模块的状态以及数据是我们更为关心的,比如接口返回支付成功,测试人员必须去看订单状态是否支付成功,买家的钱是否被扣了等,使用自动化做严格的结果判断略复杂了一点;异步接口的运行结果也不能简单的判断请求返回,而是需要自己sleep后去确认或者发消息给另一个监控让其去确认结果。财付通的接口测试基本上都可以用自动化平台去做,用自动化平台的好处是学习门槛比较低,缺点就是不够灵活,只能用平台上提供的api完成一些事情,遇到无法处理的要让测试开发在平台上提供支持。微信支付的接口测试基本上是用开源测试框架如nosestest去完成,优点是自由,可定制;缺点也是过于自由,走了很多歪路,代码结构不统一啦,公共逻辑不复用啦。总有些无法自动化的用例,一些是因为异常,一些是因为模块在编码的时候就没有提供可测性,这些还是需要手工去做。考虑到需求变动的维护成本,正常流程以及上层的用例是优先实现的,对于全面细致的自动化,测试团队还是有顾虑的。
测试过程中,给定输入,观察接口的输出,然后状态和数据是否正确,这些都是外部的结果。在程序内部,逻辑是否按照既定的路线来走呢,也许一个计算器我输入0,0返回的是0+0=0,实际上是做了0*0=0的计算,也许日志中会打印一些东西来帮助你判断,但很多开发不做自测我也就不奢望他们在可测性上有什么建树,那就自己改代码好了,加一些日志输出。类似的坏事我并没有少干,一些异常的模拟我也倾向简单粗暴的改代码。比如代码是先执行sqlA,对执行结果判断,再执行sqlB,对执行结果进行判断,执行时间间隔很短。怎么去做执行sqlA成功,执行sqlB失败的测试?
- 如果sqlA和sqlB不在一个数据库,那么在sqlB所在的数据库上搞下让他执行失败就好了
- 如果sqlA和sqlB同一个数据库,但不同库表,用类似rename sqlB的表,再恢复好了
- 如果sqlA和sqlB同一个数据库,但同库表,甚至操作类似,都update同一个字段,但值不同,那怎么搞?要不加个sleep,在sqlA执行成功后去折腾下sqlB,然后就走到执行B失败的情况了,或者干脆就改掉sqlB让他语法错误好了。当然也许有更优雅更好的办法,但是当时的测试氛围更讲求的是速度搞定
非充分测试
曾经做过的2个项目
项目A
项目A是运行几年的老项目了,一直没有大的起色,但产品仍然有需求,开发也有些优化,那时我刚来,然后交给我负责,一年来兢兢业业完成了各种测试任务,测试得很充分,没有漏测bug,项目时间不紧张,所以没有过提发延期,然后无声无息的项目组解散了~~
项目B
项目B是部门的攻坚项目,开发熬夜写代码,然后就交付给测试,要求短期内测完上线,期间各种加班各种push开发和产品解决问题,最后终于赶工完成上线,然后成了明星项目。
我喜欢项目A,项目又不是很忙,跟开发学习了下他们的自测方法,然后自己可以按自己的节奏去测试,尤其是去深入尝试一些测试方式,这在项目B中是体会不到的。但实际工作中,越是重要的项目,越难充分测试,类似项目B这样赶时间交付的占了大多数情况
测试时间往往是不够用的,因为一方面在工作量评估的时候,对于时间是要精确把控的,不计buf,估算出一个时间,换算成预计完成时间写入项目计划中。而实际测试时间一般都会超过评估时间的,这里面偏差的原因有环境问题、开发bug阻塞、需求变更等,可以将原因反馈出来;另一方面也有存在dead line的项目,比如5.1搞个活动,那么5.1前活动必须上线,但有可能工作量估算测完最快都要5.2。
怎么办?你可以提出来说这个实在搞不完要延期,然后产品和项目经理跑过来苦苦哀求,说上不了线他们就完了,测试一般都是心地善良的人,说要不我加加班,然后产品和项目经理嘴角一丝淫笑,阴谋得逞了。当然也有加班实在完不成的,因为测试的效率一般是很平稳的,不像开发写代码若才思如泉涌,本来要写一周,duang!用打字的速度一天写完了。这时候大家就提议验下主流程就上线吧,然后补充一句:测试要控制风险!
对测试来说,回答能否这样上线,主要考量是能否识别出风险和把控风险。就像有一次周五走了下冒烟流程,结果正常但发现进程处理的有点慢,然后周六开发leader打电话说要不先仍上线看下,我想了想这里有个疑问而且模块还是核心模块就拒绝了,结果周一开发看了下说有个地方循环了N多次,测试环境数据量小只是慢了点,线上就挂了,于是逃过一劫。很多人对于能否控制风险没有什么自信,一方面是能力的问题,另一方面不愿承担风险。在腾讯,大家基本上都是从项目而不是流程的角度去考虑问题,愿意承采用灵活的处理方式,同时承担相应的责任,我觉得这是一种很好的品质
(一则法人深省的例子:怎样让你的团队花6天修改1行代码 )
在时间紧张的情况下,把功能验完,把活干完是第一要务。自动化用例编写在版本提测前就需要把基本用例写好,能用开发的环境调通就先调通,在执行测试的时候再来花时间写代码和调试不可控且浪费时间,而写好api代码然后自动生成测试页面,在上面进行手工测试是更为常用的方式,因为执行起来比写自动化用例快,没有太多回归的话,效率损失不大,在提发后再将自动化用例补齐。总体上来看,这并非时间节约的方法,而是时间腾挪的方法。真正减少时间的方式只有砍用例,将用例分层分级,最上层的基本流程是一定要保证的,剩下的是非基本功能的分层测试是否能砍,砍完之后看下其他基本功能的底层测试是否能再压缩一下,这也是风险比较高的地方,可能你知道自己有30%没有测到,但是否保证没有大bug在这30%里,是需要仔细思考的。
后记
篇幅过长了~~有空就先写到这,以上是个人的体会,可能离经叛道,请轻喷,最后收个尾
以前我觉得测试的目标是消除代码中的bug,后来发现消灭所有bug并不可能,再后面体会到让开发一开始就写出高质量的代码,比让代码fix后达到发布标准更为重要。测试的方式根据项目的需要从以前更全面更细致的充分测试,逐步转变成快速有效风险可控的测试,再变为辅助开发的测试,心情也会有些起起落落。
测试工程师似乎有一种群体性忧虑,在论坛上或者知乎上,总会有人问:”做测试有前途么,测试是否已经不重要了?”一个角色是否重要在于团队是否需要他提供的服务,质量贯穿在研发流程里,肯定是需要的,但不同团队对质量的要求不一样,目前测试作为质量的主要保证方,被看作是团队重要的一部分,然而将来某一天测试会消失(也许是测试方式的消失或者是测试职位的消失),大概是因为有能代替测试职能的角色,或者是测试提供的质量服务已经满足不了团队的要求,比如项目要求自动化测试,那么只会手工测试的就不需要了,项目要求开发自己做测试,那么测试的工作逐步就转向辅助开发进行测试的方向上来了,GOOLE那样更多的SDE更少的TE也许是未来的趋势。
如果真没人要了,那就顺应潮流转变为团队所需要的类型呗,比如将来我很看好的程序员鼓励师,呵呵。
How Tencent Tests Software