为什么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

让安全实践在敏捷团队落地

随着安全得到越来越多的关注,一些跟安全相关的理论(比如BSI)脱颖而出,尽管这些理论提出来已经有一段时间,却很少看到其在开发团队被成功地应用。我们知道微软曾在十多年前就提出了SDL,却没能在业界推广开来,并不是人们不认可微软这种“从软件生命周期保障安全”的理念,而是考虑到其落地实施的难度,很多企业知难而退,那么这些安全理论对我们的软件安全真的有帮助吗?安全实践能落地吗?

很幸运地,我有机会在一个成熟的敏捷开发交付小组中经历了“从完全没有安全实践到BSI”的过程,我们也曾遇到过很多困难,但最终得到了客户的认可,并成功把安全实践推广到了整个团队,所以想跟大家分享一下我们是如何将安全在敏捷团队落地的,希望能给大家一些帮助。文中会拿Web系统举例,但一些落地的实践同样适用于非Web系统。

为什么安全理论很难落地?

结合对一些团队的了解,原因大多来自以下三个方面:

  1. 认为安全不重要
  2. 认为安全太难,需要很广很深的领域知识,只有专业人员才能做到
  3. 不知道应该用什么样的流程来做安全

那么针对第一点,因为我本身也是交付团队的一员,我观察到的大多数软件开发团队,不管是业务分析师、开发人员、测试人员、体验设计师还是项目经理,都很少有人真正把“安全”作为非常重要的一件事情,尤其是在交付压力比较大的情况下,我们都会舍弃对于安全的投入,而花时间在更容易可视化出来的用户功能上。安全,很多时候就像灭火器,如果不发生火灾,我们甚至都感觉不到它的存在。那么,安全,真的重要吗?

换位思考一下,如果我们是用户,面对以下两种选择,我们会选择哪一种?

  • 系统A:设计非常完美,功能缺陷几乎没有,性能也很棒,但是没有做任何跟安全相关的防护,用户的敏感信息很容易泄露;
  • 系统B:设计比较差,有一些功能缺陷,性能也差一点点,但是采取了特别多的安全措施,能够保障用户的数据安全性;

相信几乎所有人都会毫不犹豫选择B系统,除非这是一个完全没有用户敏感数据、完全不需要安全保障的系统(那这样的系统又有什么用?),所以只要我们把自己放在产品使用者的角度,而不是产品制造者的角度,就能很容易地理解和认可安全对于软件系统来说是比功能更重要的一个因素,安全是软件的灵魂。

那么对于很多已经深刻认识到安全重要性的团队,为什么依然很难将安全理论落地呢?原因大多来自前面提到的第二点和第三点,一是从技术上认为安全是一个很难的领域,需要专业的安全人士;二是从流程上不知道该如何开展;从这两个角度出发,“安全”需要巨大的投入,所以很多团队望而却步。那么安全真的这么难落地吗? 接下来我会简单介绍一些Web安全知识,然后通过我所在团队的落地过程给大家一个答案。

如何让安全在敏捷团队落地

什么是Web安全?

所谓Web安全问题,就是攻击者可以通过非正常的手段,获得Web系统访问权限,从而破坏网站行为,盗取甚至修改用户数据的一系列问题。

那么为什么攻击者可以获得Web系统权限呢?这种几率到底有多大呢?如果可能性非常小,我们是不是不必花费太多精力在安全上面呢?

我们来看一下Web系统的组成,一个最简单的系统都至少有这么几个部分:

如上图,浏览器发送请求到服务器,服务器给浏览器响应,服务器会查询数据库,数据库返回结果。在这个过程中,我们开发的Web程序不可避免的存在安全漏洞,甚至我们开发系统所使用的编程语言也会有安全问题。在开发时,我们常常会引用一些第三方的工具、组件,而第三方的安全性也没有办法保障,甚至数据传输过程中使用的协议、操作系统本身也会有安全问题。所以可以想象一下,如果我们不做任何的安全防范,那么每一个软件都是一个非常脆弱的系统,很容易出现安全问题。

常见的Web安全问题

既然这么多环节都有潜在的安全风险,那么该如何着手呢?可以参考OWASP TOP 10,以便对最严重的Web应用程序安全问题有个大致的了解。

敏捷开发模式现状

我们是一个已经实施敏捷开发七年的团队,一共有五十多人,划分成不同的Feature小组进行日常的工作,其敏捷开发模式已经非常成熟,我所在的Feature小组有6个开发人员,1个业务分析师,1个QA,我们每个小组的交付模式都是这样的:

如上图,以用户故事为单元,所有的用户故事都会经历一个从分析到最后给客户演示的生命周期,多个用户故事组成一个Feature,然后我们会进行Feature的功能测试,给客户展示整个功能,最后在发布之前,客户会邀请第三方的专业安全公司做渗透测试,然后找我们的开发团队修复安全缺陷。

那么这种方式有什么问题呢?

  1. 守门员模式,安全测试非常滞后
  2. 安全问题的修复时间非常有限
  3. 只有少数人关注和了解安全
  4. 依赖独立的渗透测试

所谓守门员模式,指的就是把所有的问题和风险都留在最后,靠少数人来保障,在当时的开发模式下,第三方的安全公司就是我们系统的安全守门员,可想而知,如果我们的团队对安全没有任何了解,在用户故事的开发阶段引入的安全问题要等到发布之前才能够被发现,安全测试是非常滞后的,反馈周期特别长。

另外当第三方的安全公司发现问题,留给我们团队修复问题的时间特别有限,因为渗透测试是发布前的最后一个阶段,长时间的修复又会导致发布延期,所以经常会导致安全修复以补丁的方式发布。

而且除了少数修复过安全缺陷的开发人员对安全有一点点了解之外,团队内是没有人关心安全的。

最大的问题是,所有的安全防范都依赖于最后的独立渗透测试。虽然因为执行渗透测试的是专业的第三方安全公司,他们有专业的安全知识,可以发现很多公共的安全问题,也可以提供专业的极具权威性的安全报告,但这种方式的渗透测试有个致命的弱点,他们对业务知识了解不够,很难发现跟业务相关的安全问题,而这一类的安全问题又占了相当大的比重。

可以看到,这种敏捷开发模式的现状就是:试图将安全注入一个已经成型的系统中。

安全落地尝试

那么了解了之前开发模式存在的问题,安全又这么重要,客户和团队都希望可以改变这种现状,提高安全质量,减少补丁,让每一个人都关心安全,但是我们都担心安全需要巨大的投入,会影响功能的发布,所以我们决定选择一个Feature小组做为安全试点,目标周期为一个月(我们的发布周期),观察投入产出比,然后决定是否要在整个团队实行。

首先我们小组开始学习BSI,我们认为它所传递的是这样一些理念:

  1. 将安全融入整个软件开发过程中
  2. 所有团队成员一起为安全负责
  3. 安全的设计和实施一个持续进行的过程

那么在一个几乎没有安全知识储备的团队中,如何将以上理念在团队应用呢?我们遇到了很多的困难,比如:

  1. 不知道怎么把安全和日常开发结合起来
  2. 不知道如何编写安全需求,怎么做安全测试
  3. 接受了很多安全培训,不知道如何下手
  4. 对安全缺乏专业的认知,对安全开发和测试没有信心
  5. 不知道如何满足客户期望

分析这些困难,我们开始迈出了艰难的第一步。

首先,召集团队的核心成员(包括了业务分析师,开发人员,测试人员,技术主管),同时我们邀请了公司的一位安全专家帮我们解答难题,大家头脑风暴,参考OWASP TOP 10, 结合曾经项目上出现过的安全问题以及对于业务领域的深入了解,尝试总结属于我们自己的安全问题项目并且和OWASP TOP 10进行关联,比如我们讨论后的成果是这样的:

可以看到,我们总结出来的这十项并不是将OWASP TOP 10调换顺序这么简单,我们是针对业务需求,有针对性地进行了重新整理和组织,比如其中的Sensitive Data Exposure,我们就结合项目将它划分成了四类(1.Authentication,2.Error Handling,3.Code Leak,4.Cookie Management),之所以会划分的这么具体,是因为我们自己的TOP10更贴近实现。另外我们还针对每一项添加了项目上的例子作为参考,让团队每一个人都清楚地知道我们自己的TOP 10都是什么样的以及业务场景下可能出现的安全问题。

然后我们将项目专属TOP 10作为模板加入到了每个用户故事中,这么做有两个好处:

  • 第一,业务分析师在写用户故事的时候,可以将其作为参考来编写安全验收标准;
  • 第二,如果业务分析师在缺乏安全知识的情况下很难编写安全需求,我们可以将其直接作为安全需求以防遗漏。

当然这还远远不够,更理想的情况是在需求分析阶段、业务分析师和客户在讨论需求的过程中尽量参考一些基本的原则,比如最小权限原则,来确定和编写更加准确的安全验收标准。如下图。还可以让更多的人参与到需求分析阶段,通过威胁建模等手段分析出更全面的安全需求。当然这就需要我们的业务分析师增加安全相关的知识储备,我们也在向这个方向努力。

然后在用户故事的启动阶段,业务分析师、QA和开发人员会一起针对用户故事模板中我们自己的TOP 10进行筛选,将和用户故事相关的内容标识出来作为安全验收标准。如果在故事分析阶段,业务分析师已经遵循一些原则细化了安全验收标准,在这个阶段,也可以多个角色针对这些安全验收标准进行探讨,确保大家理解一致。

到了用户故事的开发阶段,通常开发人员都会按照验收标准来编写代码和测试,基于我们已经有了足够的安全验收标准,相应地,开发人员也会编码来实现这些安全条件并且添加相应的自动化测试保障,当然,除了满足安全验收标准之外,我们也会做一些静态代码的扫描和第三方依赖的扫描,双重保障。

用户故事的验收阶段非常重要,因为如果在这个阶段发现缺陷可以快速修复,我们一般是QA、开发人员和业务分析师一起,逐个验收我们之前制定的安全验收标准。当然,除了简单地从前端进行验证,针对安全验收我们需要借助一些工具(如Burp Suite),绕过前端修改请求,检查是否后端接口也作了相应的防范,如果发现安全问题,会在这个阶段及时修复并且增加相关的测试保障。

07

到了用户故事的测试阶段,QA会做跟安全相关的探索性测试,在这个阶段,需要QA从一个全新的视角来做测试,之前我们的模式是从正常用户的角度来测试功能,而针对安全的探索性测试则截然不同,我们要用攻击者的角度来思考问题,尝试各种看似不可能的手段,寻找安全漏洞。另外,在这个阶段,我们也会借助一些自动扫描工具(比如ZAP),来检测是否有一些通用的安全问题。

08

安全的演示阶段比较有挑战性,前面提到过,它不像功能需求那么可见,所以我们采用了一种全新的方式去展示,通常功能演示我们是给客户展示用户界面,如何使用系统等,而对于安全,我们尝试了展示安全缺陷以及我们的缺陷分布分析。比如在这一个月里,我们发现了六个安全问题,其中两个是通过ZAP扫描出来的共通的安全问题,另外四个是和业务强相关的安全问题(比如账户A可以通过特殊手段修改其本来没有权限的数据,属于我们自己的TOP 10的Authentication那一类)。

回顾整个过程,其实我们在用户故事的每个阶段都增加了和安全相关的实践,并且让团队所有人员都参与了进去,将安全融入到日常的工作中,不断改进,持续关注,而这些正是BSI所传达的理念。

客户看到我们的安全成果展示后非常满意,进而在我们整个团队开展了这样的安全实践。

在维持这样的安全模式几个发布周期之后,我惊喜地发现我们的开发人员开始有了安全的意识,比如前不久我们有一个用户故事需要实现一个邮件模板,系统要求能够接受用户定制化的html,功能实现非常简单,可是开发人员一筹莫展,接到用户故事后马上找到我,探讨如何让我们的系统允许接受html后还可以避免script攻击,这让我深刻感受到,BSI(Build Security in our DNA)这个理念的精确含义,我们不是为了让大家遵循实践而去实践,而是让每个人都有安全的意识,每当我们接触到一个新的功能,马上会想到可能有哪些安全问题,而不是急于实现功能,长此以往,安全就真的进入了团队的DNA。

总结

回想之前我们想要开始在团队实施安全时的恐惧以及止步不前,到最后我们成功将安全实践落地并且推广,这个过程让我体会到,从一个小组开始尝试,观察投入产出比,再推广到整个大的团队是个很好的实践。

另外,不要期望一步到位、迅速成为安全专家,安全的设计和实施是一个持续进行的过程,可以从日常工作中的点滴做起,从保障每一个安全需求做起,想象一下,如果我们每一个用户故事都注入了和安全相关的实践,那么feature就会是这些安全的用户故事的结合,系统就会变成一个充满安全投入的整体。

和之前“靠最后的渗透测试来补救安全问题”的方式相比,这种从源头就将安全渗透进软件系统的方式更能保障我们软件的安全。


更多精彩洞见,请关注微信公众号:ThoughtWorks

Share

敏捷QA,从入门到放弃

做敏捷QA五年多,看到了很多人加入,也看到了很多人放弃。其中有经验丰富的测试人员,也有刚刚步入职场的新人。虽然“从入门到精通”是大多数人选择进入这个行业的初衷,但是敏捷QA一些特有的工作方式和要求,会让很多人不适应或者不喜欢,所以很多时候我们看到的是一个个“从入门到放弃”的过程。

那么什么样的人应该不要选择或者尽早放弃敏捷QA这条路呢?本文试图给大家提供一些参考。

敏捷QA入门

QA(Quality Assurance)通常指的是质量保障,也有一种说法是质量分析(Quality Analysis),在敏捷软件开发团队中,我们强调所有成员(业务分析师、开发人员、专职QA)为质量负责,所有人参与跟质量相关的活动,所以从宏观意义上来说,人人都是QA,很多文章都有相关的介绍,这儿不再继续探讨。本文提到的敏捷QA,指的是敏捷团队中专职的QA角色,他们的主要职责是主导并促使跟质量相关的活动在团队内发生,包括但不仅限于测试。

敏捷QA的入门阶段除了要有基本的测试知识外,必须要熟悉一些敏捷相关的基本概念以及实践,比如用户故事、迭代、迭代计划、回顾会议等等。敏捷QA几乎会参与整个用户故事的生命周期,从分析,启动,开发,验收,测试到最后的展示,尤其在启动,验收和测试这三个环节发挥着非常重要的作用。

另外,敏捷QA会同时工作在多个迭代当中,在进行当前迭代用户故事的测试验收等活动的同时,也经常需要做前一个迭代的收尾工作以及下一个迭代的准备计划等。

敏捷QA放弃

了解了基本的敏捷QA知识后,我们来看看放弃敏捷QA的四个理由。

  • 不爱说话?别做敏捷QA了

如果你之前是安安静静专心找软件缺陷的工作模式,那么进入敏捷团队你可能会经历很长时间的不适应。

因为敏捷QA不能被动地等待软件完成交到你手里再做测试,不能发现缺陷后不管不顾等着开发人员自发地去修复。你需要从软件的源头开始介入,在软件的整个生命周期中全程参与。

敏捷软件开发强调质量内建,在用户故事的生命周期中,作为质量保障的主要负责人,你需要在每个阶段跟不同的角色反复确认和验证,确保团队对需求理解一致,还要保证跟质量相关的活动发生,比如确保开发人员添加了相关的自动化测试等,所以你需要和团队的每一个成员以及客户有非常多的交流,而最直接有效的方式就是说话,沉默寡言是行不通的。

所以,如果你不喜欢说话,那么Tester也许比敏捷QA更适合你。

1-QA-talkative

  • 心态不好?趁早放弃

不知道你是否经历过这样的场景,在某些小餐厅等位严重的情况下,你需要站在某个快要结束用餐的客人边上等空位,而有些人却可以在用餐结束后无视旁边焦急等待的人群一直占着座位专注地聊天。

虽然这种行为不是很好但也无可厚非,换个角度想,这种人的心理是非常强大的,因为很少有人能够不顾及别人而我行我素。而这种“能力”对敏捷QA是非常有用的,比如在故事验收环节,这个阶段就是业务分析师、开发人员和QA三种角色一起在开发人员的机器上验证用户故事是否被正确地实现。当然任何角色都可以主导这个环节,但效果最好的是由QA来主导,因为可以提前发现缺陷并快速修复。

但是因为这个阶段所有角色都会参与,大家关注点又有所不同,所以心态不好难免就会有各种顾虑,比如,自己会不会太慢了?会不会耽误太多人的时间了?别人会不会很着急?

太多顾虑就会影响你做验收测试,尤其验收阶段的探索性测试。从而使你不能充分发挥QA的作用,而这个环节对于敏捷开发模式下的质量保障来说非常重要,这时候如果具备前面提到的强大的心理素质,就能专注地按照你的想法测试你的场景,当然可以配合一些解释让别的角色了解你的思路,而不是左顾右盼思前想后影响这个阶段的发挥。

所以,如果没有强大的心理素质,也许应该考虑趁早放弃做敏捷QA。

2-strong-heart

  • 对业务、代码没兴趣?敏捷QA不适合你

相信很多人进入测试这个行业,是因为对测试领域的技术和方法论有浓厚的兴趣,但是对于敏捷QA来说,仅仅对测试感兴趣是不够的。

敏捷QA需要对整个系统以及业务足够熟悉,这样才能从QA的视角帮助业务分析师和团队发现业务不合理或者缺失的部分(可以在故事审查或者启动阶段帮团队澄清需求)。

另外如果可以具备一些编码能力,对于做敏捷QA也是非常有帮助的。当然,术业有专攻,并不要求每个QA都会写代码,但是要对代码有一定的兴趣,愿意听开发人员讲解他们的逻辑和实现,并通过提问题了解他们的思路,至少了解他们编写的测试代码。因为在验收阶段,敏捷QA会通过审查开发人员的自动化测试是否合理和全面,来帮助团队建立对自动化的信心。

所以如果对业务、代码没有丝毫兴趣,那么也许敏捷QA不太适合你。

3-QA-content

  • 不会管理工作的优先级?做敏捷QA很难

敏捷QA最大的挑战是,每时每刻都同时工作在很多事情上,我们可以细数一下敏捷QA的活动:当前迭代的故事审查、故事启动、故事验收、故事测试用例准备、部署、缺陷管理、缺陷分析,前一个迭代的故事收尾,后一个迭代的测试计划、故事审查、故事启动等等。

另外敏捷QA希望可以做的更多,比如日志分析、性能监控、安全测试等等。

可以看到,敏捷QA的工作是非常杂乱琐碎的,而且大多活动是和团队中不同成员一起进行的,我听过很多刚刚加入敏捷QA的新人抱怨没有自己思考的时间,忙乱没有目标;也见过很多优秀的测试人员转做敏捷QA后因为不适应这种多线程的工作选择了放弃。确实,在这样一种工作模式下,如果QA不能清晰定义自己工作的优先级,就会被各种杂事牵着鼻子走。

不擅长管理自己的工作任务、不会划分优先级,做敏捷QA会非常难。

4-priority

总结

敏捷QA,不管性格还是心态,都需要足够强大,否则在整个工作过程会非常艰辛;另外仅仅掌握专业的测试技能是不够的,还需要更多地了解业务甚至代码;最后必须能够管理自己工作的优先级,否则会事倍功半。

5-summary

了解了这些方面后,可以认真思考一下,自己是不是真的适合做敏捷QA。如果依然坚持步入这个领域,那么希望我们可以一起从入门到精通。

Share

敏捷软件测试常见的七个误区

敏捷软件开发是从1990年代开始逐渐引起广泛关注的一种新型软件开发方法,是能够应对快速变化的需求的一种软件开发能力,它作为一种新型的开发模式,被越来越多地应用到软件项目中。

敏捷软件测试指的是在敏捷软件开发过程中跟质量相关的一系列活动,和传统意义上的软件测试有很多区别,因为敏捷软件测试的概念一直比较模糊,所以经常会有人走入误区,我曾经在瀑布型的软件开发模式下做过几年的测试人员,所以在刚刚接触敏捷项目的时候也曾有过一些误解,但是在敏捷软件开发团队工作将近5年后,对很多问题有了新的认识,以下针对几个常见的误区和大家分享一下我的理解。

不需要测试策略

测试策略关注的是目标和方法,即怎样在限定的时间内有效利用有限的资源达到提前制定的目标,一般制定测试策略时会首先明确测试目标,然后确定需要哪些测试类型,各种测试类型所占的大概比例,选择测试框架,最后规划一下软件发布前需要经历哪些测试阶段。

很多人认为,敏捷软件开发以用户故事为单元,是不是集中精力在用户故事测试就足够了?是不是根本不需要考虑测试策略?

其实这是一个很大的误解,因为敏捷软件开发通常都是迭代式的发布,周期比较短,资源非常有限,这就更需要我们统筹规划,小到一个用户故事,大到一个完整的用户特性,都需要考虑怎么合理利用测试资源,所以敏捷项目是非常需要测试策略的。

具体到实际项目中,通常团队会在项目初期(迭代0)制定测试策略,明确目标(包括功能性需求的目标以及非功能性需求的目标),然后确定在开发阶段需要添加哪些自动化测试(包括单元测试,接口测试,契约测试,集成测试,系统级别的UI的用户场景测试),并规定这些测试的大概比率(符合测试金字塔),选择自动化测试框架(比如XUnit)以及需要哪些手动测试(包括探索性测试,可用性测试等),还要规划每个发布周期需要进行的测试阶段(比如新功能测试,回归测试等),之后测试策略会对敏捷团队的开发及测试起到非常重要的指导作用,当然,每个团队因为项目的不同策略也会不同。

下图就是一个简单的敏捷测试策略介绍:

1

不需要测试文档

测试文档通常包括测试计划,测试用例,测试报告,测试缺陷等文档以及相对应的可以指导测试的一部分需求文档。

很多人会认为,敏捷软件测试是不需要文档的,敏捷宣言中有一句“工作的软件 高于 详尽的文档”,尽管敏捷宣言最后提到了“右项也有价值,我们更重视左项的价值”,但人们往往会忽视右项的内容,导致在很多刚开始实施敏捷开发的团队中完全否定了测试文档的作用。

首先不可否认,在实际的敏捷项目中,确实很少见传统意义上的正式的专门的需求文档和测试文档,但这并不代表敏捷项目没有文档,比如用户故事本身就是需求的载体,用户故事中的验收条件就是敏捷测试文档的一部分, 另外很多敏捷软件项目都会采用BDD的方式进行开发,将测试用例用业务人员能够看懂的自然语言描述,并结合自动化实现,形成一个融需求和测试为一体的文档,而且为了应对敏捷软件测试变化快文档更新不及时导致的问题,很多敏捷项目都在使用Living document

3

纯自动化测试 or 纯手动测试

有些刚接触敏捷的人认为敏捷软件开发发布周期很短, 测试人员根本没有时间做手动测试, 所以应该采用纯自动化测试。

也有一些人认为,敏捷开发强调快速响应变化,如果投入成本在自动化测试上,那么肯定会导致维护自动化测试带来的资源浪费,所以应该采用纯手动测试。

这是两种极端的误解,虽然这两种观点所考虑到的难点确实存在, 因为在敏捷软件开发过程中, 迭代通常比较短,确实不会预留足够多的时间来做手动测试, 所以必须要有足够多的自动化测试来保障。

然而因为测试代码本身可能存在缺陷,而且有很多部分难以被自动化测试覆盖(比如界面的测试,可用性测试,探索性测试等),所以敏捷测试也同样离不开手动测试。

至于关于自动化测试维护成本的顾虑,敏捷项目也确实存在变化比较多的特点,但通常变的都是比较接近用户的部分,所以应该尽量减少用户级别的依赖界面的自动化测试,而多增加一些不容易变化的底层的单元测试接口测试等。

推荐敏捷测试以自动化测试为主,手动测试为辅。

2

敏捷QA = 敏捷Tester

在很多刚接触敏捷实践的团队中,大家对敏捷QA的认识还停留在Tester的阶段,认为只要用户故事开发完成之后,QA去专职地做测试,发现缺陷就够了。

这是一个很大的误解,首先QA(Quality Assurance/Analyst),不是单纯意义的测试人员,通过这个角色的名称我们可以看的出来敏捷QA强调的是质量保障和分析,而不单纯是测试产品。

在实际的项目中,敏捷QA通常会从需求分析阶段就开始参与整个软件开发过程,通过在不同阶段和团队中的不同角色合作,帮助整个团队对质量达成共识,并通过在不同阶段的确认和验证做到缺陷预防,而不是等到软件开发完成后再去发现缺陷,所以对于敏捷QA来说,其目标是软件开发完成后能够发现的缺陷越少越好,而对于Tester来说,发现越多的缺陷证明工作做得越优秀。

4

非功能性测试不重要

非功能性测试指的是针对非功能性需求(软件本身满足用户需求所必需的功能性需求以外的一些特性,比如安全,性能,可用性,兼容性等)的测试,通常包括安全测试,性能测试,可用性测试,兼容性测试等。

在敏捷软件项目中,需求被切割成了很小的单元,在切割的过程中,非功能性需求是最容易被人忽略的一部分,而这导致的问题就是非功能性测试经常被团队忽略,久而久之,就会形成这样一个误解,认为非功能性测试是不重要的。

这个观点非常不对,首先非功能性测试的重要性并不会因为软件开发模式的不同而有所不同,尤其安全测试和性能测试的重要性正越来越多地被重视起来,因为很多产品必须考虑到用户敏感信息的安全以及性能导致的用户满意度,在敏捷项目中由于软件会尽早发布,如果这些非功能性需求出现问题,就会更早地造成影响,很可能在软件刚步入市场就损失掉大多数的用户。

所以非功能性的测试和功能性测试同等重要,在实际的项目中,比较好的做法是将这些非功能性需求也加入到用户故事的验收条件中,在整个敏捷开发流程中对这些非功能性需求进行验证。

5

质量是QA的事儿

受传统观念的影响,很多人还是会认为质量是QA的事儿,如果产品发布后质量不好是QA的问题,其他角色和质量没有太大的关系。

首先这种认识太高估了QA对质量的作用,软件的质量是在软件开发过程中逐步形成的, 从需求分析阶段是否真正的了解到了客户想要的功能,到开发阶段是否增加了足够多的自动化测试保障,是否写了足够健壮的产品代码,到最后测试阶段是否测试了功能引入后整个系统的可用性,不同用户路径是否能正常工作等等,这些都是软件质量的组成部分。

可以看得出来,在整个过程中,软件的质量离不开敏捷团队各种角色的付出,其中有业务分析人员对需求的准确把握,有开发人员对产品代码的高标准实现,对自动化测试覆盖率的保障,还有QA在整个过程中对质量相关活动的实施和保障,包括需求分析阶段从QA的视角对业务的补充,开发阶段对自动化测试的审查,以及探索性测试可用性测试等对产品质量的进一步保障。

所以在敏捷测试中更多时候我们会淡化角色的概念,强调团队人人都为质量负责,这样更有助于团队的每一位成员都把质量作为非常重要的一部分,而不是依赖于某个人或者某个角色。

6

开发可以写测试,不再需要QA了

因为敏捷团队强调人人都为质量负责,开发人员会采用TDD等方式写大量的自动化测试,那么是不是就不需要QA了?

对于这个观点,在社区有过很多激烈的讨论,比如这篇文章《我们需要专职的QA吗?》就曾经引起了很大的争议,其实个人认为这篇文章里提到的QA指的是Tester,具体两者的区别可参考前面的观点;抛开这个,作者的某些观点其实是很有价值的,比如作者最后提到了质量不是测出来的,要通过软件生命周期各个阶段相关活动的保障,而这些活动都离不开QA的参与。

首先需求分析阶段,QA可以从不同的视角对于需求提出疑问,补充,修改,因为QA特有的技术背景,对于软件的可用性等有更深入的理解,所以往往可以提出不同于业务分析师和开发人员的观点;开发阶段,QA也会审查开发人员写的自动化测试,通过QA的专业测试背景帮助开发人员写更有价值的测试,比如我们在项目中曾经发现开发人员写了很多没有业务价值的测试;测试阶段,探索性测试,可用性测试,安全测试,性能测试等都是QA们在做的事情。

当然,如果业务分析师从各种视角把业务分析的透彻完美,开发人员可以写非常有价值的测试,也可以做各种类型的手动测试,那么去掉专职QA也不是不可以,那样的话不是不需要QA,而是人人都是QA。

7

结论

以上列出来的七点是刚刚接触敏捷测试时很容易进入的误区,甚至有的观点在一些已经施行敏捷很长时间的团队中仍然存在,这些观点很容易导致敏捷测试走上弯路,以上是结合实际项目经验个人的一些思考,希望对大家有所帮助。

Share

用了ZAP,你的软件就安全了吗?

近来几年,很多大型网站频发安全事件,比如2011年众所周知的CSDN密码泄露事件,2014年eBay也因受到攻击造成用户密码和个人数据泄露,Web安全逐渐进入人们的视野,安全测试也逐渐成为了软件测试中非常重要的一部分。

提到安全测试,很多人应该都会想到ZAP,ZAP(Zed Attack Proxy)是OWASP提供的一款免费Web安全漏洞扫描工具,用户可以通过设置浏览器和ZAP的Proxy,在开发过程或测试过程中自动检测Web应用程序是否存在安全漏洞,ZAP还会提供扫描结果的风险等级,修复建议以及一些参考文档,下图就是ZAP扫描后的一个用户界面。
ZAP

 

除了自动扫描功能,ZAP也支持手动安全测试,通过在数据发送到服务器之前手动修改请求信息来测试Web应用程序是否存在安全漏洞。

很多人会有这样的疑惑,ZAP能否扫描出所有的安全漏洞?ZAP扫描出的安全漏洞和安全等级是否可靠?用了ZAP,软件是不是就安全了?

ZAP局限性

首先虽然ZAP的自动扫描功能非常强大,但对于OWASP Top 10中的某些项或者Top 10以外的一些安全漏洞,想要通过ZAP扫描检测出来是非常困难的,比如Top 10中的A5 “Security Misconfiguration” 就很难通过扫描检测出来,所以ZAP所能扫描到的安全漏洞只是OWASP Top 10的一个子集。

其次,ZAP扫描后的安全报告,还是需要结合实际项目进行分析才能确定其有效性和安全等级,比如我们在项目中曾经用ZAP扫描出了 “Cookie set without HttpOnly flag” 的安全隐患,推荐的解决方案是将所有的Cookie都设置成HttpOnly,但现实的情况是项目中前端AJAX需要携带这个Cookie来给后端发送请求,如果设置了这个flag,那么我们正常的请求也会失败,所以这个漏洞对我们来说就是无效的,或者说我们是不应该修复的。

另外因为Web应用程序往往比较复杂,会有很多组成部分,比如前端、服务器端、数据库等,各层分别使用了不同的框架、语言,而且经常会引入一些第三方的库、框架或者模块,每一个环节都有可能存在安全隐患,所以仅仅依赖ZAP是不够的,比如针对第三方组件的安全测试,就可以借助OWASP提供的另外一款工具Dependency Check。

通过分析实际项目中发现的安全问题,我们发现缺陷大体上如下分布:

 

Defects分析

安全问题可以归为两大类:

  • 一类是比较有共性的,即可以抛开业务上下文,软件之间共通的一些问题,常见的比较严重的安全隐患,如XSS攻击,CSRF攻击等,ZAP可以帮我们扫描出大多数的问题。
  • 另一类是针对业务需求的,比如非授权的账户是否不能访问/修改他们没有权限的信息等等,对于这一类问题,离开具体的业务上下文,是很难测试的,因为什么样的用户具有什么样的权限往往是业务领域的知识,换句话说,这一类问题的测试重点是看正常的用户能否按照业务需求所期望地正常使用系统,怎么区分evil user并阻止其对系统的使用和破坏,需要很强的业务背景。

举一个简单的例子,比如一个Web系统有两种角色,管理员和普通账户,业务需求是管理员可以修改所有人的所有信息,普通账户只能看到和修改自己的信息,如果普通账户张三可以通过一些非正常手段修改李四的信息,或者非系统的用户(evil user)通过某些方式可以看到系统内账户的个人信息,这些都是严重的安全缺陷,而且这一类的缺陷所占比率比较大,但是都没有办法通过ZAP扫描出来,也没有办法脱离对业务知识的了解来进行测试。

安全内建

ZAP扫描,针对业务上下文的用户权限测试(不能局限于界面,还要通过其他一些方式比如修改请求)以及evil user的用户场景测试,可以覆盖绝大多数的Web安全缺陷,但是正如我们没有办法将质量注入一个已经成型的产品一样,安全也是同样的道理。

如果我们在软件已经编码完成之后再引入安全检查和测试,那么软件的安全质量已经确定,后期的修复只能解决已经发现的安全漏洞,不能让软件更加安全,而且对于这些安全缺陷,发现得越晚,修复的成本就会越高。

所以为了开发安全质量较高的产品,除了选择好的工具以及增加业务背景下的安全测试,还非常有必要将安全检查和测试提前,在软件开发各个过程中引入安全实践。

微软提出的SDL(Security Development Lifecycle)就是这样的理念,SDL提出了很多软件开发过程中非常好的的安全活动,比如需求分析阶段的“最小权限原则”,开发阶段“弃用不安全的函数”,以及测试阶段可以使用“模糊测试”等等,其核心理念就是将软件安全的考虑集成在软件开发的每一个阶段,从需求,设计,编码,测试,到最后的发布整个过程中,下图是一个简化版的SDL流程图,完整的SDL还包括前期的培训,发布后的响应等:

 

SDL

 

ThoughtWorks提出的BSI(Build Security In),即安全内建,强调的也是安全提前的理念,结合敏捷软件开发实践,将安全融入到用户故事的生命周期中,引入安全验收条件, 不同角色(业务人员、开发人员,测试人员以及客户)在用户故事的每个阶段对安全验收条件进行沟通,检查,验证,确保在用户故事交付之前满足了定义的安全验收条件,下图就是用户故事的生命周期图以及在各个阶段哪些角色会参与哪些安全活动的一个简单介绍:

QQ20160405-0@2x

在保证用户故事满足了安全需求的基础上,基于迭代/发布还会有一些整体的功能级别的验证,做到真正的安全内建。

以上两种理念强调的都是把安全作为跟功能一样重要的考虑因素,在软件开发的各个阶段进行沟通和反复验证,很多实践经验也表明,将安全活动作为软件开发过程的一部分来执行,其安全效益要大于临时的或者零散的安全活动。

结论

所以从安全测试的选择来看,我们不能单一依赖某种工具,比如ZAP扫描,而应该多加入一些基于业务需求的安全测试,多从攻击者的角度思考问题,更重要的是,可靠的安全测试只能避免安全漏洞造成更大的危害和影响,并不能打造安全的产品,真正的安全产品必定需要整个软件开发过程中每个环节的保障,需要从业务分析阶段就将安全作为重要的考虑因素,将安全实践融入到整个软件开发过程中,所有角色共同参与,这样才能做到真正的安全内建。

Share