书籍点评 Web 测试囧事——从测试角度照照开发的灯下黑

testerhomebook · 发布于 2017年08月15日 · 最后由 yoyoqiekenao 回复于 2017年09月26日 · 3073 次阅读

雷辉:ThoughtWorks高级质量保证工程师,多年研发与测试经验,丰富的大型商业软件的测试工作实战经验,精通自动化、性能和探索式测试,以在软件中发现各种隐藏Bug为乐。

我是TW一名测试人员,不敢说是老司机,还算资深吧,因缘际会入了IT,做得测试这一行。其实按照大学的专业,我现在应该是一名杰出的销售大师,哈哈。然而,一入IT深似海,回头已是中年身。我有多年的Java开发经验,后来转为测试,对开发和测试都有了解,所以今天打算从测试角度出发,为开发人员照照灯下黑。

当我们在本机自测时,通常漏测的是什么

完成一个功能卡的简化流程是这样的:程序员开发→自测→QA测试。通常开发一张卡的工作量为1~3天,少量卡需要5天左右。从过去的数据看,从开发接手的卡,90%以上都有Bug,没有Bug的卡比较少,要么是功能特简单,不易出错,要么是开发经验老道又细心。

又年轻、工作年限又短的工程师们通常漏测的点在哪里呢?

1. 自测过程中没有跑通所有的分支业务流程

有时系统需要和第三方的系统进行集成,开发工程师对第三方系统不熟悉,自测过程中,有不少分支流程没有执行,恰巧就在这里隐藏着很多Bug。当系统业务过于复杂,开发只熟悉某一部分,在这种情况下自测时,需要放在完整的业务流程中测试,真实地去使用,会碰到意想不到的事情发生。我们团队开发一个类似Jenkins的持续集成平台,最近给构建过程增加了多阶段(Stage)构建的功能,用户可以在每个Stage执行不同的任务。

开发自测时,通常都会覆盖主流程,如:

  • 多Stage正常构建;
  • 多Stage构建中出现失败的流程;
  • 多Stage构建过程中被取消构建。

还有更多的流程分支需要测试:

示例1构建包的使用原则 。当一个Stage有过一次成功构建,即便该Stage下一次构建失败,它之后的Stage仍然可以使用上一个Stage最后一次构建成功的包。

示例2特殊流水线 。系统中有多个流水线,其中发布流水线与其他流水线实现不同,需要单独测试。

示例3被忽视的运行方式 。开发自测时常用手动或者自动模式进行构建,但系统还提供了定时运行方式,需要测试定时运行时多Stage是否构建正常。

示例4修改Stage后对构建的影响 。删除或修改某个Stage信息,是否会对构建产生错误的影响。此外需要查看在"历史页面"模块,是否正确显示对Stage修改的各个历史版本记录。

示例5与其他模块的关联 。只有一个Stage时,报表可以显示构建过程中单元测试结果。变成多个Stage后,如果每个Stage做了不同的单元测试,报表还能正确显示吗?

开发人员自测时候没有跑通所有的业务分支流程,主要原因在于企业开发都是团队协作,一个小组十多个人,每人日常工作中,做的功能卡比较散:今天给页面加滚动条,明天做XML的解析。对功能卡的上下游使用场景难以了解得十分清楚。

这是一个困难点,但换一个思路,将来出现了Bug谁来修?大多数情况还得自己去修复。到那时还是要去熟悉和了解上下游的使用场景,但修复的成本就会变大很多。

开发一个功能时,多花费时间去了解上下游使用的场景,看似多投入的时间,可以有效减少Bug的出现,此外,还可以让自己更了解整个产品的全景图,了解每张卡给用户产生的业务价值。因此,认真分析功能卡的上下游场景,对产品质量和个人成长都很有好处。

2. 不熟悉用户真实使用的场景和方式

一个小例子:开发一个系统对外提供的Web Service服务,当我们把这个接口的使用场景都分析到,才能做到Bug更少。

需要测试的场景包括:

  • 用户使用时会输入错误数据,后台要做校验。否则把这脏数据插入数据库中,会给系统带来不可预知的问题。
  • 使用这个接口的用户常常需要根据返回的HTTP Code做下一步操作,我们自己需要验证返回的HTTP Code是否都用对了场景。别把该返回401Not Found的场景用了500 HTTP ERROR。
  • 接口有在外网使用的场景,需要在HTTP和HTTPS加密的情形下都测试。
  • 在外网使用,黑客会制造特殊的字符来做注入攻击,系统对这些特殊字符有没有过滤?
  • 服务接口会被多个第三方程序调用,线程安全做好了吗?会不会把A的数据插入到B的名下?
  • 服务的响应能力应该怎样?50个并发每秒,还是200个并发每秒?

做每种软件的测试,都需要仔细分析其使用场景。

示例1 :开发只在Chrome浏览器上进行了自测,而用户使用的是除此之外的其他浏览器。浏览器兼容性的问题非常多。

示例2 :用户使用手机软件时,常因坐姿不同而旋转屏幕。自测时就需要关注屏幕旋转对界面布局的影响。

示例3 :自测时只在界面上建了3~5个组件,而用户可能会新建N个。在实际使用中发现,新建组件一旦超过30个页面,反应就会明显变慢,存在性能问题。

示例4 :一个Web Service服务要被用在公网上,却只在HTTP下进行自测,没有在使用HTTPS加密的场景中进行测试 。

……

3. 对测试数据的边界值选择不够充分

大部分的Bug出现在边界值附近。需要理解业务逻辑,理解输入数据的含义,来确定边界值在哪里。

例如,一个医保本允许登记0~10家医院,那0个、1、 9、10、11这些数字都是这个功能的边界值,此外还要随机挑选1~10中的任一数字进行测试。

测试完上面的场景,还要注意的就是:

  • 如果这个数字超过数字允许的最大最小值范围,会出现错误吗?
  • 超过Integer允许存储的字节长度后,系统会怎么处理?
  • 如果超出了数字的范围,使用文本做测试数据,后台有正确处理吗?
  • 换成空字符串呢,如果这个空字符串又恰巧是NULL这个程序常用关键字呢?

除此之外,那些特殊字符:引号、星号、问号是否都被正确处理了呢?别小看这些引号、星号等的处理,如果没处理好,可能会抛出HTTP 500 ERROR异常,还可能会暴露后台代码异常堆栈,给黑客提供可循的机会。

对一个英文系统来说,它的文本处理边界也许是所有的英文字符,这时候可以输入中文和德文字符,看会不会造成系统问题。

4. 开发的功能属于页面的一部分时,需要回归测试整个页面

功能开发过程中,可能会破坏以前的功能。最好快速的对页面的其他功能做回归测试,不能只关心当前完成的部分。

5. 不够细心

软件界面上经常看到按钮布局没有对齐、位置差几个像素,或者是页面上的树形结构展开时,垂直虚线中间有中断的现象;或者是字体和系统其他模块使用的字体有差异等。这些可以归到一个字上—— 。开发通常会得到UI设计稿,而UI设计稿中对字体、高度等都有细到像素级别的描述。页面元素较多,可能是导致开发变慌的原因。

从使用上来说,把自己当做用户,就能轻而易举地发现这些不细心之处。 如果是金融和银行软件,出现此类细微错误,作为用户怕是不敢把钱放进去的。重视细节才能凸显专业。

6. 开发软件前,缺少对同类产品的对比研究。

经过对同类产品的详细对比分析,我们能快速发现自己开发的软件有哪些不足,以及有哪些可以提升的地方。

如何让测试变得更有趣,更高效?

1. 不喜欢用文字描述测试用例,此话没毛病

我不喜欢写测试用例,工作中也很少写测试用例。除非是某个功能业务比较复杂,需要用文字帮助梳理和记忆思路的时候,才写一点点测试用例。

测试用例的主要问题在于,用文字描述各种逻辑分支、界面,使用的文字量大,还容易变身老版本,需要维护。好一点的方式是用BDD(我用的是Cucumber+Selenium+Java)去描述测试用例,然后用后台的自动化代码去把测试用例自动化起来,这样就不容易变成老版本了。

2. 喜欢探索性的测试过程

探索性测试第一步,先选择最简单的Happy Path,看系统反馈的直观感受。这个过程中,我注意到界面上的下拉选择框不是通用的HTML控件,如果是自定义的,这时就要担心自定义控件的JavaScript代码是否都能正常工作。

第二步,用这个下拉框选择一个最简单的选项,看选择过程是否流畅(如果不流畅,先记上一笔,可能是JavaScript代码中存在性能问题,待功能测试完成后,再回头看这里的性能)。此外,检查选中后移除选择项的删除等按钮是否正常。最基本的功能测试完了,再选择多个选项,用特殊的数据测试。

如果这个控件所在的页面,有其他HTML控件,当从别的页面跳转到这个页面时,有的控件的值没有预填写,就要测测这个自定义的控件,在同样流程中,能否把值预填写成功。

最后,界面上这个控件宽度被固定,就要考虑如果选择项值是一个150个字符的合法数据,会怎么显示。页面布局是否会被破坏?

就这样,一步一走,通过系统的反馈,点燃新的测试思路,并一步步执行测试。

在探索性测试过程中,最重要的是:测试人员要有能力根据系统给出的反馈,想出更多的测试路径去验证,或者有选择地去重点测试某一个部分。

这种能力是建立在大量的IT认知上的,IT知识越丰富,被系统激发出的思路就越多。这就好比,让一个不了解玉石的人去检验一块玉石的真伪一样,只有具备丰富的玉石知识后,才能练就一双火眼金睛来。

3. 足够了解后台的实现原理

当我们足够了解一个东西时,我们才更清楚它的薄弱环节在哪儿。做过很多开发工作,有很多开发经验的人,拿到一个软件,差不多就知道这个软件的实现过程,以及该软件可能出现问题的位置。

示例1 :一个测试Web服务返回HTTP Code的功能卡,因为返回值计算过程简单,出错概率不大。但由于返回有十多种值,需要写很多分支,这种情况程序员往往会漏测一两个分支。

示例2 :知道JSON数据的格式,就应联想到把大括号、中括号等作为数据的一部分进行测试。

示例3 :有缓存机制,在性能测试时不用同一个关键字进行压力测试,而要改变关键字。

示例4 : 如果单元测试用了Mock机制,要清楚Mock往往在系统交接处漏测Bug,需要另外进行端到端的完整流程测试才行。这就要求我们熟知Mock的使用原理。

示例5 : 自定义的HTML组件,需要写大量的JavaScript代码,这里容易出错,需要着重测试,而通用的HMTL组件的测试就不用花费过多精力。

示例6 : 了解测试环境的差异,比如后台部署多台服务器会带来Session复制分发的问题,这就需要在多台服务器的测试环境中,测试Session复制分发是否正常。

4. 善用各种测试工具

示例 :测试发送邮件时,需要验证多种邮件客户端接收后的界面排版是否正常。有这样的工具可以帮助我们只发一封邮件,它给你显示出各种邮件客户端的排版。但是也不能全信它们,使用前最好自己做抽样检查,看看这个工具是否真如它所说的那样好用。

  • Charles可以改变发送数据包的内容,帮助我们达到快速测试目的。
  • 页面加载的性能测试,使用当地的服务器访问,自动求多次请求后的平均值的工具也能帮我们节省很多时间。
  • 优选测试工具,可以让测试工作事半功倍。

5. 关注整个开发流程,有效减少Bug出现

① 在程序员开发一张卡时,首先大家会坐在一起,包括QA、BA、DEV、UI等,讨论这张卡的接收条件,避免一开始写代码就走偏的情况。

② 开发完成后,会在本机给QA演示功能,QA给出反馈,减少Bug出现在部署环境后才被发现的可能。

③ 小组的Code Review可以帮助QA减少测试工作,Code Review能及早发现代码的潜在问题。

关注单元测试覆盖率。单元测试覆盖率不高,QA的工作会越做越累,每次新加的代码都可能破坏之前的功能。

此外,还需要关注UI自动化的运行情况,它可以弥补单元测试没有覆盖到的地方。

6. 对于重复的手工测试,尽量自动化它

自动化的方式包括:

  • 单元测试;
  • UI自动化测试(需要考虑如何写出高可复用的代码);
  • 接口自动化(例如使用Jmeter的BeanShell生成数据、从CSV或者数据库中读取数据、进行断言等);
  • 自己写程序生成测试数据等。

以上是我的一些拙见,以作引玉之砖,欢迎大家补充和探讨:bug_big_bang_in_web_testing@outlook.com

本以为日子就在找地鼠和打地鼠的日子中流逝,直到有一天,黄勇问我,要不要一起写书,写关于测试的书。于是有了这本《测试囧事》,也希望本书为大家的开发和测试之路点亮了一排路灯。

共收到 10 条回复
110

不瞎推荐,这本书写的不错,看起来非常轻松愉快

4389
110Lihuazhang 回复

温总作序😊

5953

已经全部看完,挺喜欢的。看完后,默默地对功能测试做了总结,觉得自己需要提升的地方还是好多那。

110
5953wolf 回复

来个读后感呗。写的好,可以再赠一本给你。。。

5953
110Lihuazhang 回复

一个月前写来,就是写的比较不好😂
https://testerhome.com/topics/9398

15628

已购,看完再来说说对实际工作有何影响

110
15628P_Oliver 回复

会有一些共鸣的愉快

12450

书的价格贵,且很薄,内容勉强还行。

Db42eb
12450siwen 回复

+1

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册