项目实施DevOps时,我们是如何做测试的

正如我们所知,DevOps最近几年很风靡,很多企业正在如火如荼的推行它。然而,你可曾想过,从传统到敏捷、再到DevOps,开发模式的不断革新对测试提出了怎样的挑战?

最近我们项目在实施DevOps,因此想趁热打铁,就DevOps模式下如何做测试,谈一谈自己的认知。

正如我们所知,DevOps最近几年很风靡,很多企业正在如火如荼的推行它。然而,你可曾想过,从传统到敏捷、再到DevOps,开发模式的不断革新对测试提出了怎样的挑战?

最近我们项目在实施DevOps,因此想趁热打铁,就DevOps模式下如何做测试,谈一谈自己的认知。

DevOps有什么特征

DevOps是一系列软件开发实践,强调开发人员(Dev)和运维人员(Ops)之间的沟通合作,通过自动化流程,使得软件构建、测试、发布更加快捷、频繁和可靠。

1. DevOps强调一种文化

在很多企业中,开发和运维人员通常隶属于不同部门,有着不同的工作环境,采用不同的沟通方式,使用不同的开发或运维工具,并且有着不同的业务目标,这使得他们之间形成一道参不透的墙。

DevOps实际是一种文化上的变迁,强调开发、运维、测试等环节之间的沟通合作。意在帮助这些人向着一个共同的目标努力:尽可能为公司提供更多价值。为了支持这种合作的发生,需要在团队内部文化和企业组织文化两个层面做出努力。

2. DevOps是一种实践

所谓DevOps,就是将敏捷方法延伸到Production!

DevOps主要是为了将敏捷开发实践扩展到运维阶段,进一步完善软件构建、验证、部署、交付等流程,使得跨职能团队能够完成从设计到生产支持等各环节的工作。

3. DevOps包含一系列工具链

DevOps是一种融合了一系列基本原则和实践的方法论,并从这些实践中派生出了各种工具。这些工具体现在软件开发和交付过程的不同阶段:

  • 编码:代码开发和审阅,版本控制工具、代码合并工具
  • 构建:持续集成工具、构建状态统计工具
  • 测试:通过测试和结果确定绩效的工具
  • 打包:成品仓库、应用程序部署前暂存
  • 发布:变更管理、发布审批、发布自动化
  • 配置:基础架构配置和部署,基础架构即代码工具
  • 监视:应用程序性能监视、最终用户体验

DevOps对测试提出了哪些挑战

刚参加工作时,我参与了某Audi系汽车电子的软件研发,采用的是传统瀑布开发模式。在整个项目生命周期中,前半部分设计和编码,后半部分用来测试。然而我在东家工作了两年,也没能等到产品交付到用户手上。直到去年,我们的软件才得以量产并投入市场。在这4年中,产品从未交到用户手上,因此无法验证它所带来的价值,也没有任何机会得到用户反馈从而适应变化。

后来,我又参与一个银行项目,我们采用敏捷的开发模式,全功能团队,开发测试并行,每2-3周就交付一个版本。但因为没有真正发布到生产环境,我们仍然无法及时得到有效的用户反馈。

现在,我们采用DevOps的优秀实践,开发和运维协同工作。每个迭代完成,或者每修复一个线上缺陷就立即部署到生产环境。这样,我们就能够迅速从用户处获得反馈并且快速做出响应。

通过参与传统、敏捷和DevOps的项目,我深深地感受到流程的改进对团队以及项目的产出和质量所带来的改变。

那么,这些改变究竟是对测试提出了什么样的挑战? 我认为有以下几点:

1. 频繁部署

在采用DevOps之后,我们能够根据项目具体情况做到每天甚至一天多次部署。在生产环境频繁部署软件,最大的挑战就是测试。以前,测试基本上都在开发阶段之后和产品上线之前完成。但现在,不再有充足的时间留给QA团队去发现问题再抛给开发团队来修复。那么,速度成了测试面临的一大挑战。

2. 自动化

DevOps强调将流程自动化,测试作为其中一个重要环节,势必要大规模实现自动化。因此测试人员的自动化编码能力正在面临极大的挑战。

3. 实践和反馈

敏捷提倡我们要拥抱变化,更多的是要适应需求的不断变化。虽然一部分功能性需求是明确又具体的,我们清楚的知道用户想要什么,也因此易于测试。然而,也有一些非功能性需求的验收标准没那么明确,比如:提高应用性能达到良好的用户体验。我们如何才能验证用户体验是否真的良好呢?仅仅通过性能指标吗?当然不是,满足指标只能说明一部分问题,唯有真实的用户数据和反馈才是可最靠的。

4. 协作

敏捷强调全功能开发团队的共同协作,但这仅仅止于开发阶段。而DevOps注重Dev、Ops和QA三个群体之间的密切协作。因此,良好的角色定位能够帮助测试人员将价值最大化。

我们是如何做测试的

Laurent曾经在Hiptest上发表了博客《Shift left and shift right: the testing Swing》,提出了一个有意思的测试矩阵,从四个维度进行分析,描述了当软件开发模式从瀑布到敏捷、再到DevOps转型时,测试该如何响应变化。

Laurent提出一个测试左移和右移的概念:

  • 测试左移,就是指在开发阶段之前定义测试。
  • 测试右移,就是直接在生产环境中监控,并且实时获取用户反馈。

在敏捷开发的生命周期中,我们通过每一次迭代来丰富和更新产品,以使其最大限度地符合客户对系统的需求。当时测试的关注点基本停留在开发阶段,以保证产品达到上线标准。引入DevOps之后,我们不仅要关注产品的质量是否达标,还需要使价值假设得到及时的验证。因此,我们不仅要将测试左移,在开发环境验证功能的可用性,还要进行测试右移,通过监控产品在生产环境的运作情况,来验证其价值并获得反馈,从而持续改进。基于这些理解,我在项目上做了初步的尝试并取得良好的效果。我将这些尝试和实践总结为以下几点:

1.如何保证新功能得以实现?

在开发环境,我们开发新功能,并且通过测试保证其达到产品验收标准。

首先,使用BDD(Behavior Driven Development,BDD)的方式定义用户需求,这样用特定的语言来描述用户行为,能够使各个角色(测试、开发、产品负责人、市场等)对业务价值达成一致的理解,从而使其从需求到最后的测试验证,进行高度的协作和沟通,最后交付最有价值的功能。同时,QA能够提前Review故事卡,补充验收标准。除此之外,BDD方式的用户需求可以直接指导测试,后续我会写到。

其次,采用单元测试来验证最基本的代码逻辑。在编写单元测试时,建议Dev和QA Pair工作。单元测试可以认为是编码的一部分,要对系统的代码逻辑有深入的了解,因此,Dev是最合适的人选,而QA可以帮助测试覆盖的更全面。

最后,每一个功能都要严格按照故事卡的AC(Acceptance Criteria)进行验收,并采用探索性测试方法来对新功能进行无死角测试。

2.怎样验证新功能的价值?

我们将新功能部署到生产环境以后,接下来就应该衡量业务价值是否达到预期

验证预期的一个好方法是衡量用户的行为变化。比如:在上传图片的功能后面添加了一个预览按钮,但用户却极少用它,很可能是因为用户根本不需要这个按钮,或者按钮放在了不恰当的位置导致用户不方便使用,亦或是按钮样式不够友好,导致用户没有欲望使用它。这时候,该按钮的业务价值就没有真正达到,是时候调整一下了。

3.如何确保已有功能不被破坏?

在软件开发中,任何代码都不可能完全独立存在,一行代码的变更也有可能导致系统的全面崩溃。那么,如何保证在开发新功能的同时,已有功能不被破坏?换句话说,如何做到全面的回归测试?人力是最高成本,也有现实的局限性,比如,人手不够,重复做同样的事情人会变得烦躁,手不够快导致效率低下等。因此,自动化测试才是不二选择。

将BDD需求直接转化为自动化测试用例。每个测试用例都应该讲一个关于应用程序的故事。当一个测试用例使用一致的业务术语定义时,它的可读性会比较高,且容易自动化。与此同时,上一个迭代的用例在下一个迭代就可以迅速转化为回归测试的基线。

支持BDD的工具有很多,比如:Cucumber。简单举个例子,如图:

BA用BDD方式定义用户需求,QA Review并补充AC,然后将其编写为自动化测试脚本。如果QA的编码能力较弱,可以让Dev协助完成代码实现的部分。这也充分说明了协作的意义。

最后,也是更重要的部分,测试应该集成在CI中。每一次Build或者每天都要去执行测试,验证已有功能是否完好。这样才会对没有预期到的变化产生的问题给出快速反馈。

另外,做一些性能测试、兼容性测试、和安全性测试等等。

4.怎样验证产品的可靠性?

有时候,某些缺陷并不是源于代码的错误,而是一个不好的用户体验,或者只有当数据达到一定量时才会出现,测试人员是无法模拟这种类型的测试的,因此直接在生产环境监控变得高效又可靠。通常我们需要监控两种特性:性能和可用性。

使用工具持续获取用户数据,或者使用log持续获取性能信息。这有助于监控产品部署到生产环境后是如何正确运作的。快速启用一个功能,在生产环境实时监控验证其业务价值,获取到有效且快速的用户反馈,加之拥有持续部署的能力,我们能够在出现问题的时候快速做出反应,从而使得我们的产品更加可靠。

这里实际上融入了《QA in Production》的理念。现如今,已经有很多工具和方法支持在生产环境做测试了。篇幅太长,这里就不做详细阐述了,请参考原文

到这里,再来回顾一下,我们的实践是否真的卓有成效。

  1. 用BDD的方式定义用户需求、编写测试,有益于不同角色之间的一致理解和共同协作。
  2. 自动化测试解决了频繁部署所带来的挑战,同时保证产品的整体功能持续得到回归和验证。
  3. 在线监控能有效地验证不确定需求,通过生产数据分析和预警问题的发生,并且快速获取用户反馈从而及时调整。除此之外,这一点也充分体现了Dev、QA和Ops的协作,像监控等原本只能Ops做的事,现在Dev或QA一样可以做。

写在最后

测试是一种活动,曾经我们通过它来验证产品是否达到上线标准。现在DevOps模式下,我们需要在各个阶段不断地执行测试活动,以达到产品质量的持续改进。

而QA(Tester)仅仅是一种较多进行测试活动的角色。敏捷一直强调“团队为质量负责”,测试不再是QA(Tester)的专属。DevOps模式更是对测试、尤其是自动化测试提出了更高的要求,也对QA的编码能力提出了极大的挑战。作为团队成员,每个人都有责任了解开发流程、提高测试技能,把好测试这一关。但是,测试活动作为QA(Tester)的主要职责之一,提高自动化测试技能,就是当下每个QA(Tester)最为紧急且重要的事情了。


更多精彩洞见,请关注微信公众号:思特沃克

Share

物联网测试地图

物联网的出现,给测试带来了很多有意思的挑战,使得众多QA开始重新思考传统的测试过程。

例如,我最近测试了一个产品,在这个产品中的移动APP会跟连接的机器产生会话。这两个设备各种各样的状态给测试场景的设计带来了特别大的挑战。下面给大家介绍一个很有用的物联网产品测试框架——物联网测试地图,它可以帮助我们管理物联网设备多种排列的复杂状态。

物联网的出现,给测试带来了很多有意思的挑战,使得众多QA开始重新思考传统的测试过程。

例如,我最近测试了一个产品,在这个产品中的移动APP会跟连接的机器产生会话。这两个设备各种各样的状态给测试场景的设计带来了特别大的挑战。下面给大家介绍一个很有用的物联网产品测试框架——物联网测试地图,它可以帮助我们管理物联网设备多种排列的复杂状态。

物联网测试因素

当我们测试简单的web应用时,通常要考虑的状态有:

  • 服务器宕机
  • HTTP请求超时
  • 网速慢
  • 授权和认证错误

测试任何互联网应用的时候,需要警惕这四种状态。对于移动应用,操作的是移动环境,需要关注额外的几种情况:

  • 离线模式
  • 在线模式
  • 杀掉Activity
  • 后台行为
  • 语言
  • 地理位置

我们再看“连接的机器”所带来的状态多样性,通常还有:

  • 机器WiFi断开
  • 机器WiFi连接
  • 机器繁忙
  • 机器休眠

这意味着即使只有上述给定的状态集,整个系统在任何时间点上可能会有96(4x6x4)种状态。

由于系统中状态转换会引入附加的约束,这些状态都不能当做独立的实体。例如,状态从“离线”变成“在线”很可能触发一系列的事件。

上述因素还仅仅是冰山一角。随着对规范的深入了解,把不同的状态跟逻辑场景结合起来将会更加的复杂。

对于静态系统的可变数据集,已有的web测试技术可以很好的用来抽取测试场景,比如all pairs(开源的配对测试工具)、等价类划分、边界值分析法等。这些技术通过淘汰的逻辑来优化测试数据集。

例如,all pairs技术会淘汰重复的数据配对组合。但是,对系统的可变状态设计测试场景时,这些技术是不可靠的,废弃的系统状态会使得系统通讯不畅。当然,这些技术对于物联网系统中的单个单元还是很适用的。

因此,非常有必要搞一个物联网测试地图。

可视化地图

大家肯定都在地理课上看过地图。但我这里所说的地图是针对测试场景的,它列出所有潜在的系统因素,在测试某个特性时可以从中抽取必要的测试场景。

产品的每个系统的n种状态在同一个可转动的圆环中列出,逻辑上相邻的状态在环中相互挨着。非功能需求(NFR)在测试复杂集成的时候很容易被忽略掉,于是把它们在一个环中单独列出。

下图就是我所说的物联网测试地图:

下面以一个例子介绍地图的使用场景,该例子仅涉及移动设备和机器交互部分,需要关注的环是设备、机器和网络。

把移动设备和机器固定在WiFi连接的状态,转动网络环,可以得到下面这些场景:

  • 未授权用户尝试访问机器会在App上触发“访问被拒绝”的错误消息
  • 服务器宕机和服务器错误会触发相应的业务错误消息——“程序出错,请稍后重试”
  • 响应超时可能有两种情形:重发同一个请求并显示“正在加载”图示,或者显示上面那样相似的错误消息
  • 非法请求会触发消息“请更新你的App”

继续保持移动设备的WiFi为连接状态,转动机器环:

  • 当机器是离线模式的时候,App应该显示“请检查机器的网络连接”
  • 当机器繁忙的时候,弹出警告“机器繁忙,无法完成请求”
  • 当机器休眠或者在另一个网络上的时候,应该显示“没找到机器”等类似的消息
  • 然后,机器调到正确的网络,应该恢复移动设备和机器的连接

切换机器环为WiFi连接,转动移动设备环:

  • 当移动设备离线时,应该弹出对应的消息或者禁掉操作按钮
  • 当移动设备恢复在线模式时,App应该发送相应的请求去连接机器
  • 当移动设备的网络从WiFi切换到3G,应该有什么样的行为?
  • 当用户正在试图连接物联网设备的时候突然接到电话,将App置于后台运行,这时候还能收到完整的请求还是需要从头开始发送请求?
  • 安卓设备杀掉一个在后台运行了一段时间的App,用户的最后屏幕状态还会保存吗?
  • 有本地化需求的App要在每个场景层面进行验证

就这样,多次旋转地图可以扩展产生多个场景。尽管有些场景可能不适合当前的特性,有些甚至跟业务需求无关,这个测试地图还是非常详尽的。

在实践层面,对于有多个QA在测试同一个物联网产品的团队,地图可以作为大家共同参考的手册。这个地图把工具、设备、场景和协议的排列以易于理解的方式呈现出来,覆盖了测试场景设计这个独特的需求,是一种非常高效的合作方式。


更多精彩洞见,请关注微信公众号:思特沃克

Share

无障碍性测试工具 Pa11y

Pa11y是基于HTML codeSinffer以及PhantomJS制作而成的网站内容A11y自动化检查工具。它利用PhantomJS的headless模式运行需要被测试的网站,然后把网页源文件和指定的规则(比如WCAG2AAA)做对比,自动检查出网页内容是否符合规范,同时会把检查结果输出成指定格式的报告。

2017.3 技术雷达 Trial

A11y(Accessibility)指的是用来帮助身心障碍者(残疾人)更加便利的使用先进技术的能力。目前世界上主要由各种人权组织和政府通过一些民间规则和政府规则来保障这方面权益。以Web Content为例,比较常见的规则有W3C组织在2008年出台的WCAG2.0,和美国国家标准的Section508等等。

这些规则数量比较多,涉及的检查范围从规定网页元素的颜色对比度,到元素的属性是否缺失等,内容十分丰富。对一个网站的内容进行完整的A11y检查,通常需要针对网站的每一个页面的每一个元素走查,这样的检查几乎是手工无法办到的。

Pa11y是基于HTML codeSinffer以及PhantomJS制作而成的网站内容A11y自动化检查工具。它利用PhantomJS的headless模式运行需要被测试的网站,然后把网页源文件和指定的规则(比如WCAG2AAA)做对比,自动检查出网页内容是否符合规范,同时会把检查结果输出成指定格式的报告。

ThoughtWorks技术雷达VOL.16将其放在试验阶段,鼓励大家对它进行尝试和使用。

Pa11y本身运行在node环境下,通过npm install安装。安装成功后,可以使用命令行来执行对目标网页的检查。同时它也支持从JavaScript直接调用。Pa11y工具支持选择WCAG2.0 A/AA/AAA标准和Section508标准,也支持忽略这些标准中某些特定的项。通过设置参数,还可以改变输出报告的格式,比如输出CSV或者HTML格式的报告。

对比之前需要在手动进入到网站的每个页面、点开每个隐藏元素,再把当前网页源代码拷进自动化工具的检查方式。Pa11y提供了Actions方式来自动化操作页面元素,使得网站操作和规则对比可以完全自动化进行。

另外和其他A11y测试工具相比,除了免费和开源之外,Pa11y还衍生出了许多不同目的的、基于核心工具Pa11y的Pa11y-X工具。比如支持并发多线测试和测试/生产环境隔离,而且可以存储每次执行结果的Pa11y-Webservice;又比如支持非技术用户使用、操作配置简单易懂、集成了Pa11y-Webserivce的前后端一体工具Pa11y-Dashboard(如下图)。

Pa11y-Dashboard还提供可视化图表,协助分析质量趋势。

另外,基于Pa11y这个核心工具还衍生出了专为CI准备和优化过的命令行工具Pa11y-CI等工具。 随着需求的增加,这个平台里面的工具也在Pa11y team的维护下逐渐增多,逐渐形成了一个A11y测试工具全家桶。

然而在目前的版本中,仍然有一些可以继续关注的地方,比如:

  1. 目前所支持的标准仅有WCAG2.0和Section508,将来是否会扩展新的规则支持方案。
  2. 2017年的WCAG2.1标准已经发布β版本,Pa11y应该如何做相应更新值得期待。
  3. 如何提升对不同浏览器的检查支持。
  4. 当前版本依赖的PhantomJS本身还有一些问题,例如对ES6的支持性不完等,如何使Pa11y在ES6开发的网站上完美运行善。

另外值得注意的是,由于Chrome59宣布开始支持Headless,PhantomJS2.x的主要开发者之一Vitaly Slobodin已经宣布不再继续开发新的功能。那么依赖PhantomJS的Pa11y是否也会迎来一次大的改版换“芯”成Chrome呢?


更多技术雷达信息,请点击这里

Share

为什么QA不喜欢重构?

作为一名QA,每次听到“重构”两个字,既想给追求卓越代码的开发人员点个赞,同时又会感觉非常紧张,为什么又要重构?马上就要上线了,怎么还要改?是不是应该阻止开发人员做重构?

经常听到开发人员抱怨 ,“这么烂的代码,我来重构一下!”,“这代码怎么能这么写呢?谁来重构一下?”,“这儿有个坏味道,重构吧!”

作为一名QA,每次听到“重构”两个字,既想给追求卓越代码的开发人员点个赞,同时又会感觉非常紧张,为什么又要重构?马上就要上线了,怎么还要改?是不是应该阻止开发人员做重构?

重构几乎是开发人员最喜欢的一项实践了,可QA们却充满了顾虑,那么为什么QA不喜欢重构呢?

老功能被破坏

不止一次遇到这样的场景,某一天一个老功能突然被破坏了,QA们感到奇怪,产品这块儿的功能已经很稳定了,也没有在这部分开发什么新功能,为什么突然出问题了呢?

追查下去发现是近期做了重构。再追问下去,对于老代码,已经几乎看不懂老的测试了,可是开发人员看到代码的坏味道就想重构,于是功能破坏了。

在快速迭代的开发模式下,QA们主要关注用户故事的生命周期,重点测试新的特性功能,所以对于老功能回归测试的投入是非常有限的,如果开发人员突然对老功能进行了重构又没有告知团队,这样的问题很可能就会进入生产环境,这样是非常有风险的。即便很多开发人员重构老功能时会告知QA,以提前发现和修复导致的问题,但无疑会大大增加QA做回归测试的负担。

新功能推迟/重复测试

按照用户故事的开发流程,开发人员完成功能后,多方角色会首先在开发人员的机器上进行用户故事的快速验收以及探索性测试,然后开发人员会提交代码,由QA拿到包之后部署到测试环境进行测试。

但有的时候QA在开发机器上快速验收之后,开发人员又进行重构,曾经经历过“故事验收的时候功能都是正常的,拿到包部署之后好多功能不工作了”的事情,跟开发人员确认,又是重构导致的。

有时候开发人员会在用户故事验收之后告知QA还会继续重构,QA可以等到重构完成后再拿新的版本做测试,这样就会导致用户故事的测试时间推迟。或者开发人员会先重构再做验收,而这样又会导致QA在开发机器上进行重复的验收测试。

无计划不可见

开发人员的重构时机对我们来说是无规律的。有的时候一边开发用户故事一边重构,有的时候会在故事完成后、QA在开发机器上验证结束后才做重构,有的是代码评审后大家指出问题后做重构,有的甚至得等到项目组来了有经验的开发人员才开始重构。对QA来说,重构的时机是无计划的。

另外重构也是不可见的。我们总谈可视化,日常的开发工作由用户故事和缺陷来可视化,而重构经常是幕后进行的,不被跟踪、不被记录、不可见,有经验的开发人员会在进行“大”的重构之前口头告知团队,如果没有告知,就在不知不觉中发生了,只有功能被破坏了才能意识到。

总结

以上列出了QA不喜欢重构的三个理由,归根结底其实都是重构不当导致的。代码重构(Code refactoring)指对软件代码做任何更动以增加可读性或者简化结构而不影响输出结果。而不当的重构往往只关注了前半部分却忽略了对输出结果的影响。

个人认为,如果能够注意以下几个方面,也许可以很大程度减少QA对重构的顾虑:

  • 充足的自动化测试是保障输出结果的一个有效途径。不管对于历史代码还是新代码,进行重构的前提应该是确保这部分功能已经被足够的自动化测试覆盖,有的开发人员认为这是一个不可行的建议,因为“充足”对于每个人每个角色的标准可能是不一样的,QA也许永远都不会觉得测试足够,但是其实可以借助测试覆盖率等度量工具,甚至直接针对功能特性由QA来定义需要哪些自动化测试,在补齐这些自动化测试的基础上再做重构。
  • 对于新功能的重构,应该融入到正常开发过程中,在故事验收之前已经完成相应的重构,因为自动化测试不是万能的,也不可能达到100%的覆盖率,所以还是需要QA验证的。这么做就意味着客户要为我们的重构买单,所以作为软件领域专家的我们,如何让业务领域专家的客户理解重构的价值,这就变的至关重要了。
  • 小步前进,尽量避免或者减少大的重构,这样可以减少突然增多的回归测试工作量,也会减少功能被破坏的风险。如果发生了大的重构,反思一下是哪里出了问题?是我们积攒了太多的技术债?还是业务领域模型发生了大的改变?然后采取措施避免类似的事情再度发生。
  • 对于一些核心功能或者组件,进行重构之前尽早告知团队QA,如果能够给QA讲解一下重构的目的以及本次重构可能会影响到的业务区域会对QA有很大的帮助。这样做一方面可以让QA把重心放在最容易受到影响的功能上加强回归测试,另一方面也能帮助QA更合理地安排测试计划。
  • 尽量避免在产品上线前进行重构,不仅可以减轻QA回归测试的负担,也会降低功能破坏后来不及修复的风险。

重构的目标是为了改善代码质量,长远来看应该是可以减少软件缺陷的,从这个角度来说QA和开发人员的目标是一致的,我们相信,如果重构恰当,必定对项目是有利无害的。

Share

从测试策略到测试架构

现在业界流行的测试金字塔和测试象限只是两种高度抽象和简化的测试策略模型,不具备实际可操作性,只具备高层次的指导性和参考性。直接根据这两个模型来工作是低效的,甚至可能带来负面效果。

文/刘冉

今年是我做软件测试的第7个年头了,当年我从软件开发转做软件测试的时候,没有想过我能在这个领域做这么久。

在这7年里面,我在软件测试领域摸爬滚打,从自动测试起步,逐步接触到软件测试的各个领域:各种测试方法(等价类,全配对等)、测试技术(单元测试,功能测试,性能测试,探索性测试等)、自动化测试工具(JUnit,Selenium,Gatling,ZAP等)、测试流程(传统测试流程,敏捷测试流程等)以及测试策略(测试象限和测试金字塔等)。

其中“测试策略”在测试业界是讨论的比较少的,因为大多数人的工作重点是设计测试用例,执行测试或者开发和维护自动化测试,而只有少部分人才会涉及到测试策略的工作,从而导致很多测试人员其实并没有系统的了解测试策略。

所以我准备将我这几年对于测试策略的经验、总结以及思考以系列文章的形式写出来,希望能稍微帮助一下大家去理解测试策略,从而做到更好的测试,减少缺陷,提高质量。

测试策略

首先来看一下Wikipedia上对于测试策略的定义:

A test strategy is an outline that describes the testing approach of the software development cycle. It is created to inform project managers, testers, and developers about some key issues of the testing process. This includes the testing objective, methods of testing new functions, total time and resources required for the project, and the testing environment.

Test strategies describe how the product risks of the stakeholders are mitigated at the test-level, which types of testing are to be performed, and which entry and exit criteria apply. They are created based on development design documents. System design documents are primarily used and occasionally, conceptual design documents may be referred to. Design documents describe the functionality of the software to be enabled in the upcoming release. For every stage of development design, a corresponding test strategy should be created to test the new feature sets.

更多内容详见:https://en.wikipedia.org/wiki/Test_strategy

所以测试策略(Test Strategy)的第一目标就是“减少缺陷的出现和发布”。其中“减少缺陷的出现”可以通过测试前移等方法来解决,在进行软件需求分析和架构设计的时候发现缺陷;而“减少缺陷发布”可以使用各种测试方法、技术来验证和测试编码完成的功能(这两点在今后的文章里面会通过不同的例子进行更详细的阐述)。

由此可见,“测试策略”并不是只由测试人员定制的,它是由一个团队的各个角色一起来制定和建立的,目的是保证软件的质量,减少缺陷。

而“测试计划”是用于实施测试策略的。只有充分理解测试策略目的和实施方式,才能充分理解测试策略,为什么要做测试策略,什么样的测试策略才更有意义、更好,怎样实施才能更有效等问题。

测试计划

测试计划在Wikipedia中是这样定义的:

A test plan documents the strategy that will be used to verify and ensure that a product or system meets its design specifications and other requirements. A test plan is usually prepared by or with significant input from test engineers.

更多内容详见:https://en.wikipedia.org/wiki/Test_plan

制定测试计划是保证测试策略能被有效执行的一种方式。它告诉了团队在什么阶段,什么样的角色应该执行测试策略中什么样测试技术和测试方法。它主要由测试人员编写,但是应该由整个团队进行评审,因为开发人员、产品经理、业务分析人员甚至用户都可能参与到测试计划的执行中。

测试计划是可以根据项目的实际进展情况进行调整的,所以它并不是一成不变的。

测试架构

在上个世纪六七十年代软件系统还处于小规模的时候,软件开发并没有谈什么架构,软件测试也不存在什么策略可言。但是随着软件规模的极速增大,复杂性也成指数级增加,专业的软件架构应运而生。

为了有效的在规定时间内完成复杂软件系统的测试,必须有一个指导性的策略来帮助团队理解、选择和组织大量的测试,因此软件测试策略就出现了。而测试策略往往是高层次的指导,对于一些中小型项目也许已经足够了,但是却不足以应付现代越来越复杂的软件系统。

因为随着微服务、移动互联网、物联网、大数据分析系统、AI系统等的出现,要测试一个包含各种技术,外部依赖,或者独立子系统的复杂系统,并不是简单的根据测试策略在不同层面上做不同的测试就可以了,而是要理清各种测试之间的相互联系和制约,然后思考怎么有效的将各个维度上的测试联系起来,以软件系统架构的思维去思考整个测试体系。

请注意这里不是说要去设计一套全自动化的测试系统来完成整个系统的所有测试,而是通个各种有效的方式(无论手动还是自动)把各种测试合理且有效的联系起来,形成一个拥有完整架构的测试体系,这样才能使整个系统的各种测试更加可视化和更易于理解,使整个系统的各种测试更加有效,避免重复测试,节约成本。

举例来说,一个前后端分离的Web业务系统不仅有前端UI和大量的JavaScirpt代码,还有后端的API和第三方依赖系统以及数据库系统,如何将各层测试有效的联系起来就是测试架构需要解决的问题。

首先,前端、后端API、第三方依赖系统和数据库系统有各自的单元测试、集成测试等,然后可以使用契约测试来测试统一前端和后端API,再使用Stub加入对于第三方依赖系统的契约测试或者监控测试,还需要使用测试数据生成系统参数,将各种测试数据存入数据库系统用于支持契约测试等。

对于不同软件系统,其架构一般都是根据业务需求、技术能力等各种条件来设计的。与软件架构一样,测试策略和测试架构在不同的项目里面,需要根据其软件系统的架构、技术栈、业务需求、人员的技能等因素来定制和设计。

再谈测试策略

现在业界流行的测试金字塔和测试象限只是两种高度抽象和简化的测试策略模型,不具备实际可操作性,只具备高层次的指导性和参考性。直接根据这两个模型来工作是低效的,甚至可能带来负面效果。所以对于测试金字塔和测试象限不能盲目的使用,而是需要根据项目的实际情况来生成适合自己项目的测试策略和测试架构,并在此基础上执行真实的测试工作。

扩展阅读:

http://www.infoq.com/cn/articles/an-effective-test-strategy

http://www.testingexcellence.com/test-strategy-and-test-plan/

更多精彩洞见,请关注微信公众号:思特沃克

Share

致测试同仁们:让我们一起做安全测试吧!

安全测试水很深,但是作为质量代言人的我们却无法置之不理。

本文首发于InfoQ:

http://www.infoq.com/cn/articles/to-test-colleagues-let-us-do-a-safety-test

今天,很多的软件并没有经过专门的安全测试就被放到互联网上,它们携带着各类安全漏洞暴露在公众面前,其中一些漏洞甚至直指软件所承载的核心敏感信息或业务逻辑。这些漏洞一旦被不怀好意者利用,很可能会给企业造成经济损失。带来负面声誉影响的同时,还可能被起诉、遭到罚款等等,细思极恐。其中的一部分原因是企业本身安全意识不强,但是很多时候虽然软件企业已经开始意识到这些问题,却苦于缺少专业的安全测试人员,他们不得不冒着极大的风险先上线赌一把运气再说。

既然如此,作为质量代言人的我们,怎能对此置之不理呢?

你也许会问?怎么理?安全测试水太深了。

安全测试并不遥远

是的,安全测试在软件测试里面是一个很特别的科目(或作“工种”),很多人都觉得这个科目应该全权交给神秘的安全测试人员来管。这个观念导致很多测试人员徘徊在安全测试的门口却迟迟不进去,包括我自己。

直到后来,我非常有幸能够在不同规模的软件开发项目上跟“神秘的安全测试人员”学习如何进行安全测试,发现“神秘的安全测试人员”不光是名字跟我们一样都有“测试”二字,所做的事情在本质上也跟我们测试人员有很多相通之处。

想想看我们都做过什么:

我们修改过url的参数,对不对?他们也是!
我们在数据输入处提供过不合法的数据,对不对?他们也是!
我们尝试过修改只读数据,对不对?他们也是!
我们也测过用户会话是否如期timeout,对不对?他们也是!

Ok,这还不是全部。他们也做测试计划、测试用例设计、bug分析与管理等等。所以,安全测试离我们并没有那么遥远。

当然,我必须承认,安全测试是非常复杂的。一个专业的安全测试专家在某种程度上来说是一个全栈工程师。所以,想要在安全测试上一夜成才不太容易。不过好消息是,作为测试人员的我们却有得天独厚的优势,使我们能够在安全测试上快速起步,帮助团队尽快展开预防并检测安全漏洞的工作。
在这里我想要跟大家分享一下在敏捷开发团队中如何利用我们的测试经验开展安全测试。

安全测试并不陌生

首先,让我们先来了解什么是安全测试,我们作为测试人员有什么可以直接用上的技能和经验。
简单来说,安全测试其实就是一个发现软件安全漏洞的过程,旨在保护软件系统的数据与功能。它跟常规测试相似的地方至少有以下几点:

No. Summary Details
1 目标类似 预防、检测系统的缺陷(尽早、频繁反馈系统质量信息)
2 在软件生命周期中的工作过程类似(以敏捷团队为例) -了解系统业务需求
-针对业务与系统功能设计用例
-与其他角色一起启动需求的开发
-与其他角色一起在开发环境验收需求
-在测试环境进行全面测试
-分析并总结测试结果
-反馈测试结果
3 测试用例有很多重合 面向用户的测试场景非常类似
4 都需要有探索的过程 对会对不同的业务场景有目的的进行探索
5 都要有测试人员必备的“怀疑态度” 对开发人员的代码保持友好而警惕的态度

1. 目标类似
不管是常规测试还是安全测试,都有一个原则:预防胜于检测。这个比较容易理解,不管是常规测试的缺陷也好,还是安全测试的漏洞也好,如果能预防使它不发生,就省了后期的修复与验证工作。如果不能成功的预防缺陷,能早一些发现的话,肯定比晚发现的修复的成本低。

2. 在软件生命周期中的过程类似

以敏捷开发团队为例,常规测试人员在各个阶段做的事情,安全测试人员也要做:

  • 了解业务的需求,以避免混乱的测试优先级;
  • 针对业务与系统功能设计用例:常规测试需要关注系统功能,安全测试同样也不能脱离系统功能;
  • 与其他角色一起启动需求的开发:沟通测试用例,避免因为沟通不足造成返工;
  • 与其他角色一起在开发环境验收需求:尽早提供反馈,发现缺陷时开发可以马上修正
  • 在测试环境进行全面测试:针对端到端的场景进行测试,尽可能把第三方系统(如果有的话)也包括进来;
  • 分析并总结测试结果:整理问题清单,排列优先级;
  • 反馈测试结果:把测试结果反馈给团队等干系人。

3. 测试用例很多重合

在面向终端用户的测试场景上,常规测试的用例与安全测试的用例是非常类似的。比如对于登录系统的功能,不管是常规测试还是安全测试,我们都会测试用户输入正确的用户名是否可以登录,输入错误的用户名或密码系统会如何反应。

比如我曾经工作的一个搜集报税人信息的系统,不管是常规测试还是安全测试,都会测试系统的登录,系统信息的录入与编辑,文件的上传等等。因为在每一个终端用户可以操作的场景上,都可能会有安全漏洞存在。所以,有了常规测试的经验,我们就相当于有了不少安全测试用例的储备。

4. 都需要有探索的过程

测试是一个了解软件系统能否完成我们预期的过程,也是探索系统还有哪些我们没有预期的行为的过程。安全测试的过程需要把探索的目标转向安全漏洞。当我们这么做时,我们同样会得到很多探索的乐趣。

5. 都要有测试人员必备的“怀疑态度”

相信咱们测试人员都非常熟悉一个场景--开发人员说:“我只做了一个很小的代码改动。”然后我们带着友好而警惕的态度,发现这个“很小的改动”引发了很大的问题。不管是在安全测试还是非安全测试,这个警惕性是我们都需要保持的良好传统。

那么,有了这么多类似的地方,还缺什么呢?如果想要做专家,还差很多。但是如果想马上安全测试上起步,我们可以先做下面的改变。

安全测试从何做起

第一,转换视角

在我看来,不管是带着全栈的经验,还是只有部分技术知识,想要做好安全测试必须先转换我们观察软件的视角。举个例子,让我们看看下这幅画:

(图片来自:http://imgur.com/gallery/ZCgQ3)

同样一幅画,有人一眼看过去看到的是两个人脸,而有人看到的是一个花瓶。这就是观察视角的不同造成的。

在我刚开始接触安全测试时就很深的体会到了这一点。当时我在测试一个Web应用的用户登录功能。当我输入错误的用户名来试着登陆时,浏览器上的提示信息为“该用户名不存在”。当我尝试正确的用户名而错误的密码时,提示信息变成“密码输入错误。”对于这个清晰的错误提示我非常满意。试想我若是一个真实的终端用户,这个信息有效的帮助我缩小纠错范围,提高效率,非常好。

可是,就在我身边坐着的安全测试人员马上跳了出来:“这个提示信息需要改!敏感信息暴露了!”看到我一脸茫然,这位安全测试人员告诉我,通过我们的提示信息,恶意的系统使用者可以推测出哪些用户名已经存在于系统中,然后利用这些用户名可以再进行密码的暴力破解,缩小破解的范围。所以,这个信息虽然为合法用户提供了便利,也为不怀好意的系统使用者提供了便利。而往往这种便利为恶意的系统使用者带来的好处远大于给合法用户带来的好处。

这个经历在让我受震动的同时,也使我意识到可能很多安全漏洞之前就摆在我的面前了,我却没有看出来,因为我把它们过滤了。事实证明,在后来经历的不同项目中,当我转换了视角,有些安全漏洞不需要我去找,而是自己跑到我眼前来的。真是得来全不费功夫。

第二,改变测试中模拟的对象

为了能从不同的视角来观察软件,我们必须改变我们所模拟的对象。这也是一个让我们刻意练习转换视角的有效方法。

我们在做非安全测试的时候通常把自己想象成一个合法用户,然后开始验证系统是否能完成预设的目标。比如对于一个网上商城,我们会验证系统是否能让用户完成商品的浏览与购买,我们也会测试一些异常的行为,比如购买的商品数量不是数字而是一串无意义的字母时,看系统是否能比较优雅的做出回应。我们这么测试的目的往往是为了确保用户误操作以后还能够继续他们的购买,或者说不要给系统造成什么严重的伤害。

如果要做安全测试,我们则必须去模拟系统的另一类使用者-恶意用户。他们的目的是寻找系统中可钻的漏洞。比如同样是一个网上商城,恶意用户的目标之一就是要想办法以较少的钱,甚至不付钱就能拿到商品。所以,如果恶意用户进行了“误操作”,他们不会停留在“误操作”,而是通过“误操作”来看系统是否给自己提供更多的线索。

所以,我们需要转换测试时所模拟的对象,把思维从一个合法用户的视角中拉出来,转换成一个恶意用户。这需要一点时间,就如同之前看到的画,如果我们一开始看到的是人脸,要想下一次第一眼看到的是花瓶,我们需要时间来刻意练习。

第三,使用专用的测试工具

有了思维的转换,我们可以加入新的测试想法。但是,在具体做安全测试的时候我们会发现并不是那么容易去模拟恶意用户的行为。毕竟系统的前端会给我们设置很多的屏障。而且恶意用户可不总是从系统前门进去的。这时候,使用一些工具,比如OWASP Zap(https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project)、Burp(https://portswigger.net/burp/)等是非常有帮助的。我们可以在系统界面上执行功能测试的用例,用这些工具来获取http请求,篡改后发送给后台服务器。有了这些实用又比较容易上手的工具,我们就可以执行很多恶意用户的操作场景了。

能做到这三点,起步就基本够用了。

举个栗子吧🌰

下面让我们以网上商城的买家在商品评价中上传图片这个功能来讲讲如何实践这“三板斧”。假设我们从项目初期就加入了,那么我们大致有七件事情要做:

  1. 识别系统中有价值的数据;
  2. 在需求分析阶段加入恶意用户需求;
  3. 针对恶意用户需求设计测试用例;
  4. 参与启动恶意需求的开发;
  5. 在开发环境验收恶意需求的实现;
  6. 在测试环境中进行安全测试;
  7. 向团队反馈所发现的安全漏洞。

不要担心,这不是7个全新的事情。只是在每个需要测试人员出现的地方增加了安全的工作而已。

1. 识别系统中有价值的数据
很多人认为执行测试才是测试,而我们的安全测试从这里就开始了。
了解业务之后,我们需要考虑系统中会有什么有价值的数据。这是为下一步加入恶意用户需求做准备。对于一个网上商城,有价值的数据可能包括产品信息、订单信息、用户信息、支付,等等。
这个环节对我们测试人员来说并没有太多额外的工作,毕竟我们做非安全测试的时候也需要了解业务。不过要注意了,我们要测试的“图片上传功能”是一个涉及有价值数据的功能。我们需要提高警惕了。

2. 在需求阶段加入恶意用户需求
恶意用户需求是用来记录恶意用户想要在系统中达到的目的。与普通用户需求的区别是,我们不是要去实现它,而是使用它来帮助我们远离对系统使用者“不恰当的信任”。通常我们需要针对每一个合法用户需求来增加一个或多个相对应的恶意用户需求。


举个例子,如果我们这个“图片上传功能”的合法用户需求为:作为一个买家,我想在对商品进行评价的时候上传图片作为买家秀,以便于参加返现营销活动。那么对应的恶意用户需求可以是:为一个恶意用户,我想破坏买家秀返现活动,以便破坏商城的营销活动。“破坏买家秀返现活动”是一个大的目标。为了设计用例方便,它可以被细分为一系列小目标。比如让用户无法上传图片、让页面无法正确显示图片等等。

有了恶意用户需求的主干信息,我们就可以开始下一步设计安全测试用例了。

3. 针对“恶意用户需求”设计测试用例
现在我们需要做的是努力把自己限制在“恶意用户”的角度做头脑风暴:“到底有什么方法可以使买家无法上传图片信息呢?”, “让页面无法正确显示买家秀图片又怎么做到?”嗯,也许最直接的办法就是让服务器所在的机房断电、断网之类的。这是些不错的想法,虽然执行难度有点大。没关系,记录下来。除此之外,我们还可以有其他测试用例,比如:

  • 使存储图片的磁盘空间被占满而无法接受新的图片;
  • 使处理上传图片的进程繁忙而无法接受新的上传任务;
  • 上传特别大的图片使用户的客户端需要很长时间才能下载完
  • 上传伪装成图片的恶意代码,进一步获取服务器权限,删除所有的买家秀图片;
  • 等等

如果这个时候想到新的测试用例也同样记录下来,比如“我想不购买也上传买家秀图片以获得返现”之类的。
不用太担心这个阶段的测试用例过于“疯狂”或者不够完整,毕竟我们对于系统的实现还不是很了解。我们会在接下来的环节中完善具体的步骤。

4. 参与启动恶意需求的开发(evil story kickoff)
在开发人员开始开发合法用户需求之前,我们需要跟业务分析人员、开发人员一起沟通需求的内容。在敏捷软件开发项目中我们叫它story kickoff,即用户故事启动。当有了对应的恶意用户需求时,我们必然也要把它也加到启动的范围里。目的是把我们头脑风暴出来的测试用例跟所有的角色来沟通。预防胜于检测。

5. 在开发环境验收恶意需求的实现

100%预防软件的缺陷与漏洞是不太可能的,所以这个环节的存在是为了提早反馈。
我曾经经历过一个项目,都快上线了才决定做安全测试,结果测出来的问题之一是用户会话(user session)不能正确过期的问题,经过一番研究,发现需要对系统设计的架构进行比较大的修改,只能做个临时的修复让系统先上线,然后再把系统的架构给改了,重写这部分功能,重新测试。代价非常高。所以不管是安全测试还是非安全测试,”在开发环境验收恶意需求的实现“这个步骤都不能缺少。

而这个环节存在的第二个目的是让我们可以从开发人员那里得到支持-具体实施的细节,帮助我们完善具体的测试用例。比如在这个时间点我们若从开发人员那里得知系统的后台没有对图片上传者做身份验证,我们就可以至少增加一个测试的用例:“恶意用户以其他用户的身份上传一个风马牛不相及的图片”。有时候错误的图片比没有图片更具有杀伤力。

6. 在测试环境中进行安全测试
终于到了运行测试的阶段。可能这个时候我们之前想到的测试用例已经被开发人员给解决了。如果是这样那就太好了。但是,事实并非有这么美好。第一,可能这些用例只是在开发环境上成功通过了,但是在理想的测试环境里,也就是类产品环境里,这些用例可能并不能完全通过;第二,肯定还有其他需要探索的地方。这时我们就可以用OWASP Zap、Burp这样的工具来辅助我们把之前的安全测试用例执行一次,同时还再可以对系统的安全性做一下探索测试。

7. 向团队反馈所发现的安全漏洞
都测得差不多的时候,我们就可以向团队以及相关干系人汇报安全测试的结果了。跟非安全测试不同的地方是,当我们反馈安全漏洞的时候,要考虑不同漏洞结合起来是否会增加系统的安全风险。举个例子:如果有两个安全漏洞,一个是系统没有很强的用户账户密码规规则,另一个是系统没有对上传图片的大小做限制,那么恶意用户把这两个漏洞一结合起来,事情就比原来风险大很多。那么我们就必须建议提高这两个漏洞中任意一个的优先级。

当我们用“三板斧”走完这七步以后,我们已经可以把很多安全漏洞都挖出来了。是不是没有想象中的难?所以,测试同仁们,让我们做安全测试吧!

Share

测试自动化后,我们需要怎样的QA?

我们先讨论一下在传统的瀑布模型下QA是如何工作的,其中最主要的问题是什么;然后作为对比,我们再来看看敏捷团队里的QA是如何工作的,工作重点又是什么;最后,我们详细看一看在新的职责下,QA应该如何做。

我们先讨论一下在传统的瀑布模型下QA是如何工作的,其中最主要的问题是什么;然后作为对比,我们再来看看敏捷团队里的QA是如何工作的,工作重点又是什么;最后,我们详细看一看在新的职责下,QA应该如何做。

瀑布开发模型

即使在今天,在很多企业中瀑布模型仍然是主流。每一个需求都需要经过分析、设计、开发、测试、上线部署、运维等阶段。虽然一些企业已经开始实施敏捷开发,比如项目/产品以迭代的方式运作,也有诸如每日站会、代码检视等敏捷实践,但是如果仔细审视,你会发现其实开发模式丛骨子里来说还是瀑布:按照软件组件划分的部门结构(详见康威定律)、按照职能划分的团队(开发和测试分属不同部门)、过长的反馈周期、永远无法摆脱的集成难题等等。

waterfall-work

随着软件变得越来越复杂,团队里没有任何一个人可以说出系统是如何运作的,也不知道最终用户是谁,以及最终用户会以何种方式来使用最终的软件。

更糟糕的是,按照职能划分的团队在物理上都是隔离的,比如独立的测试部门,独立的运维部门,整日忙碌而难以预约到档期的业务人员,当然还有经常疲于交付,无处吐槽的苦逼开发。由于这些隔离,信息的反馈周期会非常长,一个本来很容易修复的缺陷可能在4周之后才会被另一个部门的测试发现,然后通过复杂的工作流(比如某种形式的缺陷追踪系统)流到开发那里,而开发可能还在拼命的完成早就应该交付的功能,从而形成恶性循环。

瀑布模式中的QA

在这样的环境中,QA们能做的事情非常有限。在需求开始时他们会参加需求澄清的会议,制定一些测试计划,然后进行测试用例的设计。有的企业会用诸如Excel之类的工具来记录这些用例。这些写在Excel里的,“死”的用例作用非常有限。而最大的问题在于:它们无法自动化执行。另外,在实际软件开发中,需求总是会经常发生变化,需求的优先级也会有调整,然后这些记录在Excel中的“死”的用例会很快过期,变得无人问津。

除此之外,QA中的有些成员会使用工具来录制一些UI测试的场景,然后在每个新版本出来之后进行回放。然而,当UI发生一点变化之后,这些自动化的用例就会失效:比如HTML片段中元素位置的调整,JavaScript的异步调用超时等等。

显然,这种单纯以黑盒形式来检查功能点的测试方式是不工作的,要真正有效的提升软件质量,仅仅通过事后检查远远不够,软件的质量也应该内建于软件之中。QA的工作也应该是一个贯穿软件生命周期的活动,从商业想法到真实上线,这其中的所有环节都应该有QA的参与。

系统思考

如果不从一个系统的角度来思考软件质量,就无法真正构建出健壮的、让业务和团队都有信心的软件系统。质量从来都不只是QA的职责,而是整个团队的职责。

team-spirit

关于软件质量,一个根深蒂固的误解是:缺陷在开发过程中被引入,然后在测试阶段被发现,最后在QA和开发的来回撕扯中被解决(或者数量被大规模降低),最后在生产环境中,就只会有很少的,优先级很低的缺陷。

然而事实上,很多需求从开始就没有被仔细分析,业务价值不很确定,验收条件模糊,流入开发后又会引入一些代码级别的错误,以及业务规则上的缺陷,测试阶段会漏掉一些功能点,上线之后更是问题百出(网络故障、缓存失效、黑客攻击、操作系统补丁、甚至内存溢出、log文件将磁盘写满等等)。

在一个敏捷团队中,每个人都应该对质量负责,而QA则以自己的丰富经验和独特视角来发掘系统中可能的质量隐患,并帮助团队将这些隐患消除。

circle-resized

我在ThoughtWorks的同事Anand Bagmar在他的演讲What is Agile testing- How does automation help?中详细讨论过这部分内容。

QA到底应该干什么?

本质上来说,任何软件项目的目标都应该是:更快地将高质量的软件从想法变成产品

将这个大目标细分一下,会得到这样几个子项,即企业需要:

  • 更大的商业回报(发掘业务价值)
  • 更短的上线时间(做最简单,直接的版本)
  • 更好的软件质量(质量内嵌)
  • 更少的资源投入(减少浪费)

其实就是传说中的多、快、好、省。如果说这是每一个软件项目的目标的话,那么团队里的每一个人都应该向着这个目标而努力,任何其他形式的工作都可以归类为“浪费”。用Excel记录那些经常会失效,而且无法自动执行的测试用例是浪费,会因为页面布局变化而大面积失效的UI测试也是浪费,一个容易修复的缺陷要等到数周之后才被发现也是浪费。

在这个大前提下,我们再来思考QA在团队里应该做什么以及怎么做。

QA的职责

Lisa Crispin在《敏捷软件测试》中提到过一个很著名的模型:敏捷测试四象限。这个模型是QA制定测试策略时的一个重要参考:

agile-testing-quadrants

如果按照纵向划分的话,图中的活动,越向上越面向业务;越向下越靠近技术。横向划分的话,往左是支撑团队,往右是评价产品。

其实简化一下,QA在团队里的工作,可以分为两大类:

  • 确保我们在正确的交付产品
  • 确保我们交付了正确的产品

根据这个四象限的划分,大部分团队可能都会从Q2起步:QA会和BA,甚至UX一起,从需求分析入手,继而进行业务场景梳理,这时候没有具体的可以被测试的软件代码。不过这并不妨碍测试活动,比如一些纸上原型的设计:

prototype-resized

这一阶段之后,我们已经有了用户故事,这时候QA需要和开发一起编写用户故事的自动化验收测试。当开发交付一部分功能之后,QA就可以做常规的用户故事测试了,几个迭代之后,QA开始进行跨功能需求测试和探索性测试等。根据探索性测试的结果,QA可能会调整测试策略,调整测试优先级,完善测试用例等等。

根据项目的不同,团队可以从不同的象限开始测试策略的制定。事实上,Q1-Q4仅仅是一个编号,与时间、阶段并无关系,Lisa Crispin还专门撰文解释过。

关于QA如何在软件分析的上游介入,并通过BDD的方式与业务分析师一起产出软件的各种规格描述,继而通过实例来帮助整个团队对需求的理解,ThoughtWorks的林冰玉有一篇文章很好的介绍了BDD的正确做法。如果将QA的外延扩展到在线的生产环境,制定合理的测量指标,调整测试策略,强烈推荐林冰玉写的另一篇文章产品环境中的QA

其他职责

事实上,软件生命周期中有很多的活动处于灰色地段。既可以说是应该开发做,又可以说应该QA做,甚至可以推给其他角色(比如OPs)。不过我们知道,一旦涉及角色,人们就再也不会按照全局优化的思路来应对问题了。这种灰色的活动包括:

  • 持续集成的搭建
  • 测试环境的创建与维护
  • UAT上的数据准备
  • 代码中的测试代码的维护
  • 测试代码的重构

在团队实践中,这些活动我们通常会让QA和开发或者OPs同事一起结对来完成。一方面避免知识孤岛的形成,另一方面在跨角色的工作中,也可以激发出更多不同的思路。

万能的QA?

虽然在这些活动中,QA都会参与,但并不是说团队里只要有一个QA就可以了。QA在参与这些活动时,侧重点还是有很大不同的。

c2_cargo

比如需求分析阶段,如果有QA的加入,一些从QA角度可以发现的有明显缺陷的场景,则可以在分析阶段就得到很好的处理。另一方面,尽早介入可以设计出更合理的测试计划(比如哪些功能的优先级比较高,用户会更频繁使用,那么对应的测试比重也会更高)。在Story分析与书写阶段,QA可以帮助写出更加合理的验收条件,既满足业务需求,又可以很好的指导开发。

在和开发一起编写澄清需求时,主要是编写自动化验收测试,而不是实际编写业务逻辑的实现(虽然QA应该参与Code Reivew环节,学习并分享自己的观点);甚至在上线运维阶段,QA还需要和OPs一起来设计用户数据的采集指标(比如用户访问的关键路径,浏览器版本,地区的区分等),从而制定出新的测试策略。

扩展阅读

Share