文字内容
2. 测试文集 ThoughtWorks洞见 浙版数媒
3. 版权信息 ThoughtWorks洞见-测试文集 ©浙江出版集团数字传媒有限公司 2017 非经书面授权,不得在任何地区以任何方式反编译、翻印、仿制或节录本书文 字或图表。 DNA-BN:ECFP-N00009739-20170320 制作:苏野 出版:浙江出版集团数字传媒有限公司 浙江 杭州 体育场路347号 互联网出版许可证:新出网证(浙)字10号 电子邮箱:cb@bookdna.cn 网 址:www.bookdna.cn BookDNA是浙江出版联合集团旗下电子书出版机构,为作者提供电子书出版 服务。 如您发现本书内容错讹,敬请指正,以便新版修订。 ©Zhejiang Publishing United Group Digital Media CO.,LTD,2017 No.347 Tiyuchang Road, Hangzhou 310006 P.R.C. cb@bookdna.cn www.bookdna.cn
4. 目 录 QA,从1.0到4.0 敏捷软件测试常见的七个误区 为什么QA不喜欢重构? 一个遗留系统自动化测试的七年之痒 测试自动化后,我们需要怎样的QA? 从测试策略到测试架构 说起 BDD,你会想到什么? 醒醒吧少年,只用Cucumber不能帮助你BDD 我在测试移动弱网时踩过的坑 容器化时代对测试的机遇 产品环境下的QA 致测试同仁们:让我们一起做安全测试吧!
5. QA,从1.0到4.0 文/梁真 迄今为止,敏捷开发方法在各个公司都有了长足的发展, 曾经的测试人员慢慢地在向QA职能过渡,但依然很多人不了解 QA和测试的区别是什么。 敏捷实践不断地演化过程,使项目中各个角色不断弱化, 同时,对每个成员的要求也越来越高。“全功能团队”的提出, 不单单是对开发的要求,对QA来说,想要在快速变革中具备竞 争力,就现在所具备的技能来说,还是远远不够的。 简单聊聊我所经历的“QA发展史”
6. (图片来自ThoughtWorks UX设计师 高媛媛) QA 1.0——机械化流水线作业 在我实习的那年,软件领域还很少提及QA,伴随着瀑布模 型的兴起、软件工程规模的不断扩大以及市场对软件质量要求 的提高,催生出了“测试工程师”这样一个角色。那时他们的职
7. 能很单一,每天的工作就是在各种测试环境中按照详细设计的 文档,编写测试用例,并逐条测试,检查功能完整性,发现软 件中可能出现的功能缺陷,并进行追踪。 这个时期是软件测试的原始时期,对测试人员的技能要求 不高,只要对文档理解透彻,做事细心,是很容易胜任的。此 时的产出和交付物可度量,虽然如此,测试工程师只是执行 者,能力和价值都无法最大化,却被每天重复的工作所累。 QA 2.0——过程化带来不同的工作内容和价值 体现 我毕业的时候,开始接触敏捷方法,团队规模从百人变成 了仅有十人左右,信息平等取代了逐级传递,分散的信息源 (客户的每一封邮件和每一句对话都可能是我们将要做的功 能)取代了几十甚至百页的文档,测试不再仅是提出软件缺陷 和编写、执行测试用例,而是成为了团队的数据库和字典。 当用户提出一个功能的时候,测试人员可以快速地进行需 求分析,回顾并确定是否与此前的功能有冲突。当开发人员对 某一块业务不了解的时候,测试人员也可以组织会议进行阐 明。由于对业务和客户的深入了解,测试人员可以为客户提出 建设性意见和功能,有时也会是做出决策的人。 高效、频繁的沟通,大大提升了QA的软技能。此时的测试 人员已经过程化,对软件质量的理解,从“发现缺陷”提升到“对
8. 软件开发过程的质量控制和风险预估”,我们定义这样的测试工 程师为QA。 QA 3.0——自动化技能提高生产力 随着工程实践的日益成熟,QA的角色和工作日益复杂,这 使得他们在大量重复、繁杂的工作与更有意义的角色之间频繁 切换,这对软件质量也产生了一定影响。 QA从开始的手工测试、探索性测试等手段,逐渐发展成为 可以利用工具和程序对测试进行快速的回归,对软件性能进行 有效监控,无论是前端还是后端、web应用还是移动平台。这 使得自己从繁杂的重复性工作中解脱出来,去做更有意义的事 情。他们通过项目的积累以及团队成员的帮助,对测试技术有 了一定的认识。 QA 4.0——角色向多技能、服务化转型 记得几年前,前公司领导对我说,“不管开发换了什么技术 栈,你做的自动化框架都可以继续使用,对你来说没有任何影 响。”当时我也赞同,认为框架已经足够好,可以适用于任何场 景和业务。 从某个角度来说确实是这样, 测试相对于开发技术的指数 级发展,平稳的太多。不论是在互联网还是移动互联网时代, 缓慢的发展速度给了我们一种太平盛世的错觉,似乎我们掌握
9. 的技术足够坐吃几年。 来到ThoughtWorks之后,我发现了类似的事情,不论是在 交付还是咨询的过程中,会有意无意中推一些我们认为的最佳 实践,当遭到客户质疑和challenge的时候,我们似乎很沮丧。 在北京出差的日子,有幸做了一次咨询,虽然只有几天, 让我学到一件事,我们认为的最佳实践和方法,并不完全适应 于所有场合,尤其是在我们这样的咨询公司,对客户实施怎样 的方案,取决于客户的领域、产品/项目特性、用户群、技术水 平、政治文化、技术栈以及目标和期望等等。 如果对于“最佳实践”过于坚持,也会影响客户关系和咨询 效果。之后咨询同事讲的几个故事也似乎让我认识到,虽然我 们对现在的工作和技能足够的熟练,但依然不够。 我们似乎还需要具备以下的能力: 1.尝试用不同的方法写“茴” 经验丰富的QA对于测试技术中的关键点都烂熟于心,除了 我们正在使用的方案和技术,尝试用不同的语言、框架去实现 关键点和难点。这样的好处在于,我们可以通过深入的学习和 使用,对流行方法、过程和框架进行比较,了解各自的优势和 劣势,不但可以增强自身的技能,当面对不同客户的时候,也 可以给出客观的分析,为客户提供精准服务,同时如果可以对 客户现有的技术和方案、流程和方法提供有价值的意见,也可
10. 以提高在客户现场的生存率,轻松俘获客户。 2.If you cannot test it, dev it. 软件过程中,QA可以在需求分析和定义阶段介入,为项目 提供不可估量的价值,但另一方面,QA技能实践(此处指 Tech)是一个相对受限的领域,我们很难绕过未实现的代码和 工程去做更多的事情。 你可能会说,“没有做过mobile的项目,如何去学习移动端 的测试技能?”如果恰好你对行业的发展具有前瞻性和敏感度, 例如你可能认为IoT和VR是一个趋势,你却没有机会去这样的 项目中做QA。 那么我们是不是可以像开发一样,提升自己的学习能力和 适应力,保持对技术的敏感度和热忱,了解不同技术领域,对 该领域的开发、测试、构建和集成部署都有一定的了解?所 以,如果你想比其他人走得快那么一点,go dev! 3.真正的全功能 QA的领域虽然相对受限,但幸运的是角色相对不受限。在 日常的开发过程和项目积累过程中,不但能对业务有深刻的理 解、对用户行为有独到的见解,而且对技术也有一定的认识。 在需求分析过程中,QA总是可以从技术和业务结合的角度
11. 扮演好一个BA的角色,成为一个优秀的PM,甚至我们可以在 客户提出一些需求的时候尝试着从一个UX的角度去设计原型, 如果具备前端的能力,也可以自己去Dev、UI,不断拓展自己 的技能领域,使自己成为真正的全功能。 总结 真正的全功能,并不是单纯意义上让QA去做Dev,而是最 大程度弱化角色的概念,逐步强调和培养技能多元化。如何把 对需求的理解能力强化为业务分析能力,把质量控制能力强化 为项目管理能力。强化自身的优势,跳出自己的舒适区,使自 己能够轻松胜任。这样我们才不会在看到去QA和QA消亡之类 的观点后,无所适从。
12. 敏捷软件测试常见的七个误区 文/刘建华 敏捷软件开发是从九十年代开始引起广泛关注的一种新型 软件开发方法,是能够应对快速变化需求的一种软件开发能 力,它作为一种新型的开发模式,被越来越多地应用到软件项 目中。 敏捷软件测试指的是在敏捷软件开发过程中跟质量相关的 一系列活动,和传统意义上的软件测试有很多区别,因为敏捷 软件测试的概念一直比较模糊,所以经常会有人走入误区,我 曾经在瀑布型的软件开发模式下做过几年的测试人员,所以在 刚刚接触敏捷项目的时候也曾有过一些误解,但是在敏捷软件 开发团队中工作了将近5年后,对很多问题有了新的认识,以 下针对几个常见的误区和大家分享一下我的理解。 不需要测试策略 测试策略关注的是目标和方法,即怎样在限定的时间内有 效利用有限的资源达到提前制定的目标,一般制定测试策略时 会首先明确测试目标,然后确定需要哪些测试类型,各种测试 类型所占的大概比例,选择测试框架,最后规划一下软件发布 前需要经历哪些测试阶段。
13. 很多人认为,敏捷软件开发以用户故事为单元,是不是集 中精力在用户故事测试就足够了?是不是根本不需要考虑测试 策略? 其实这是一个很大的误解,因为敏捷软件开发通常都是迭 代式的发布,周期比较短,资源非常有限,这就更需要我们统 筹规划,小到一个用户故事,大到一个完整的用户特性,都需 要考虑怎么合理利用测试资源,所以敏捷项目是非常需要测试 策略的。 具体到实际项目中,通常团队会在项目初期(迭代0)制 定测试策略,明确目标(包括功能性需求的目标以及非功能性需 求的目标),然后确定在开发阶段需要添加哪些自动化测试(包 括单元测试,接口测试,契约测试,集成测试,系统级别的UI 的用户场景测试),并规定这些测试的大概比率(符合测试金字 塔),选择自动化测试框架(比如XUnit)以及需要哪些手动测 试(包括探索性测试,可用性测试等),还要规划每个发布周期 需要进行的测试阶段(比如新功能测试,回归测试等),之后 测试策略会对敏捷团队的开发及测试起到非常重要的指导作 用,当然,每个团队因为项目的不同策略也会不同。 下图就是一个简单的敏捷测试策略介绍:
14. 不需要测试文档 测试文档通常包括测试计划、测试用例、测试报告、测试 缺陷等文档以及相对应的可以指导测试的一部分需求文档。 很多人会认为,敏捷软件测试是不需要文档的,敏捷宣言 中有一句“工作的软件 高于 详尽的文档”,尽管敏捷宣言最后提 到了“右项也有价值,只是我们更重视左项的价值”,但人们往 往会忽视右项的内容,导致很多刚开始实施敏捷开发的团队中 完全否定了测试文档的作用。 首先不可否认,在实际的敏捷项目中,确实很少见到传统 意义上的正式且专门的需求文档和测试文档,但这并不代表敏 捷项目没有文档,比如用户故事本身就是需求的载体,用户故 事中的验收条件就是敏捷测试文档的一部分,另外很多敏捷软 件项目都会采用BDD的方式进行开发,将测试用例用业务人员 能够看懂的自然语言描述,并结合自动化实现,形成一个融需 求和测试为一体的文档,而且为了应对敏捷软件测试变化快文 档更新不及时导致的问题,很多敏捷项目都在使用Living
15. document。 纯自动化测试 or 纯手动测试 有些刚接触敏捷的人认为敏捷软件开发的发布周期很短, 测试人员根本没有时间做手动测试,所以应该采用纯自动化测 试。 也有一些人认为,敏捷开发强调快速响应变化,如果投入 成本在自动化测试上,那么肯定会导致维护自动化测试带来的 资源浪费,所以应该采用纯手动测试。 这是两种极端的误解,虽然这两种观点所考虑到的难点确 实存在,因为在敏捷软件开发过程中,迭代通常比较短,确实 不会预留足够多的时间来做手动测试,所以必须要有足够多的 自动化测试来保障。 然而因为测试代码本身可能存在缺陷,而且有很多部分难 以被自动化测试覆盖(比如界面的测试,可用性测试,探索性测 试等),所以敏捷测试也同样离不开手动测试。 至于关于自动化测试维护成本的顾虑,敏捷项目也确实存 在变化比较多的特点,但通常变的都是比较接近用户的部分,
16. 所以应该尽量减少用户级别的依赖界面的自动化测试,而多增 加一些不容易变化的底层的单元测试接口测试等。 推荐敏捷测试以自动化测试为主,手动测试为辅。 敏捷QA = 敏捷Tester 在很多刚接触敏捷实践的团队中,大家对敏捷QA的认识还 停留在Tester的阶段,认为只要用户故事开发完成之后,QA去 专职地做测试,发现缺陷就够了。 这是一个很大的误解,首先QA(Quality Assurance/Analyst),不是单纯意义的测试人员,通过这个角色 的名称我们可以看得出来敏捷QA强调的是质量保障和分析,而 不单纯是测试产品。
17. 在实际的项目中,敏捷QA通常会从需求分析阶段就开始参 与整个软件开发过程,通过在不同阶段和团队中的不同角色合 作,帮助整个团队对质量达成共识,并通过在不同阶段的确认 和验证做到缺陷预防,而不是等到软件开发完成后再去发现缺 陷,所以对于敏捷QA来说,其目标是软件开发完成后能够发现 的缺陷越少越好,而对于Tester来说,发现越多的缺陷证明工作 做得越优秀。 非功能性测试不重要 非功能性测试指的是针对非功能性需求(软件本身满足用 户所必需的功能性需求以外的一些特性,比如安全,性能,可 用性,兼容性等)的测试,通常包括安全测试、性能测试、可 用性测试、兼容性测试等。 在敏捷软件项目中,需求被切割成了很小的单元,在切割 的过程中,非功能性需求是最容易被人忽略的一部分,而这导 致的问题就是非功能性测试经常被团队忽略,久而久之,就会
18. 形成这样一个误解,认为非功能性测试是不重要的。 这个观点非常不对,首先非功能性测试的重要性并不会因 为软件开发模式的不同而有所不同,尤其安全测试和性能测试 的重要性正越来越多地被重视起来,因为很多产品必须考虑到 用户敏感信息的安全以及性能导致的用户满意度,在敏捷项目 中由于软件会尽早发布,如果这些非功能性需求出现问题,就 会更早地造成影响,很可能在软件刚步入市场时就损失掉大多 数的用户。 所以非功能性的测试和功能性测试同等重要,在实际的项 目中,比较好的做法是将这些非功能性需求也加入到用户故事 的验收条件中,在整个敏捷开发流程中对这些非功能性需求进 行验证。 质量是QA的事儿 受传统观念的影响,很多人还是会认为质量只是QA的事 儿,觉得其他角色和质量没有太大的关系。
19. 首先这种认识太高估了QA对质量的作用,软件的质量是在 软件开发过程中逐步形成的,从需求分析阶段是否真正了解到 了客户想要的功能,到开发阶段是否增加了足够多的自动化测 试保障,是否写了足够健壮的产品代码,到最后测试阶段是否 测试了功能引入后整个系统的可用性,不同用户路径是否能正 常工作等等,这些都是软件质量的组成部分。 可以看得出来,在整个过程中,软件的质量离不开敏捷团 队各种角色的付出,其中有业务分析人员对需求的准确把握, 有开发人员对产品代码的高标准实现,对自动化测试覆盖率的 保障,还有QA在整个过程中对质量相关活动的实施和保障,包 括需求分析阶段从QA的视角对业务的补充,开发阶段对自动化 测试的审查,以及探索性测试可用性测试等对产品质量的进一 步保障。 所以在敏捷测试中更多时候我们会淡化角色的概念,强调 团队人人都为质量负责,这样更有助于团队的每一位成员都把 质量作为非常重要的一部分,而不是依赖于某个人或者某个角 色。
20. 开发可以写测试,不再需要QA了 因为敏捷团队强调人人都为质量负责,开发人员会采用 TDD等方式写大量的自动化测试,那么是不是就不需要QA了? 对于这个观点,在社区有过很多激烈的讨论,比如这篇文 章《我们需要专职的QA吗?》就曾经引起了很大的争议,其实 个人认为这篇文章里提到的QA指的是Tester,具体两者的区别 可参考前面的观点;抛开这个,作者的某些观点其实是很有价 值的,比如作者最后提到了质量不是测出来的,要通过软件生 命周期各个阶段相关活动的保障,而这些活动都离不开QA的参 与。 首先需求分析阶段,QA可以从不同的视角对于需求提出疑 问、补充、修改,因为QA特有的技术背景,对于软件的可用性 等有更深入的理解,所以往往可以提出不同于业务分析师和开 发人员的观点;开发阶段,QA也会审查开发人员写的自动化测 试,通过QA的专业测试背景帮助开发人员写更有价值的测试, 比如我们在项目中曾经发现开发人员写了很多没有业务价值的 测试;测试阶段,探索性测试,可用性测试,安全测试,性能 测试等都是QA们在做的事情。 当然,如果业务分析师从各种视角把业务分析的透彻完 美,开发人员可以写非常有价值的测试,也可以做各种类型的 手动测试,那么去掉专职QA也不是不可以,那样的话不是不需 要QA,而是人人都是QA。
21. 结论 以上列出来的七点是刚刚接触敏捷测试时很容易进入的误 区,甚至有的观点在一些已经施行敏捷很长时间的团队中仍然 存在,这些观点很容易导致敏捷测试走上弯路,以上是结合实 际项目经验个人的一些思考,希望对大家有所帮助。
22. 为什么QA不喜欢重构? 文/刘建华 经常听到开发人员抱怨,“这么烂的代码,我来重构一 下!”,“这代码怎么能这么写呢?谁来重构一下?”,“这儿有 个坏味道,重构吧!” 作为一名QA,每次听到“重构”两个字,既想给追求卓越代 码的开发人员点个赞,同时又会感觉非常紧张,为什么又要重 构?马上就要上线了,怎么还要改?是不是应该阻止开发人员 做重构? 重构几乎是开发人员最喜欢的一项实践了,可QA们却充满 了顾虑,那么为什么QA不喜欢重构呢? 老功能被破坏 不止一次遇到这样的场景,某一天一个老功能突然被破坏 了,QA们感到奇怪,产品这块儿的功能已经很稳定了,也没有 在这部分开发什么新功能,为什么突然出问题了呢? 追查下去发现是近期做了重构。再追问下去,对于老代 码,已经几乎看不懂老的测试了,可是开发人员看到代码的坏 味道就想重构,于是功能破坏了。 在快速迭代的开发模式下,QA们主要关注用户故事的生命
23. 周期,重点测试新的特性功能,所以对于老功能回归测试的投 入是非常有限的,如果开发人员突然对老功能进行了重构又没 有告知团队,这样的问题很可能就会进入生产环境,这样是非 常有风险的。即便很多开发人员重构老功能时会告知QA,以提 前发现和修复导致的问题,但无疑会大大增加QA做回归测试的 负担。 新功能推迟/重复测试 按照用户故事的开发流程,开发人员完成功能后,多方角 色会首先在开发人员的机器上进行用户故事的快速验收以及探 索性测试,然后开发人员会提交代码,由QA拿到包之后部署到 测试环境进行测试。 但有的时候QA在开发机器上快速验收之后,开发人员又进
24. 行重构,曾经经历过“故事验收的时候功能都是正常的,拿到包 部署之后好多功能不工作了”的事情,跟开发人员确认,又是重 构导致的。 有时候开发人员会在用户故事验收之后告知QA还会继续重 构,QA可以等到重构完成后再拿新的版本做测试,这样就会导 致用户故事的测试时间推迟。或者开发人员会先重构再做验 收,而这样又会导致QA在开发机器上进行重复的验收测试。 无计划不可见 开发人员的重构时机对我们来说是无规律的。有的时候一 边开发用户故事一边重构,有的时候会在故事完成后、QA在开 发机器上验证结束后才做重构,有的是代码评审后大家指出问
25. 题后做重构,有的甚至得等到项目组来了有经验的开发人员才 开始重构。对QA来说,重构的时机是无计划的。 另外重构也是不可见的。我们总谈可视化,日常的开发工 作由用户故事和缺陷来可视化,而重构经常是幕后进行的,不 被跟踪、不被记录、不可见,有经验的开发人员会在进 行“大”的重构之前口头告知团队,如果没有告知,就在不知不 觉中发生了,只有功能被破坏了才能意识到。 总结 以上列出了QA不喜欢重构的三个理由,归根结底其实都是 重构不当导致的。代码重构(Code refactoring)指对软件代码 做任何更动以增加可读性或者简化结构而不影响输出结果。而 不当的重构往往只关注了前半部分却忽略了对输出结果的影
26. 响。 个人认为,如果能够注意以下几个方面,也许可以很大程 度减少QA对重构的顾虑: • 充足的自动化测试是保障输出结果的一个有效途径。不 管对于历史代码还是新代码,进行重构的前提应该是确保这部 分功能已经被足够的自动化测试覆盖,有的开发人员认为这是 一个不可行的建议,因为“充足”对于每个人每个角色的标准可 能是不一样的,QA也许永远都不会觉得测试足够,但是其实可 以借助测试覆盖率等度量工具,甚至直接针对功能特性由QA来 定义需要哪些自动化测试,在补齐这些自动化测试的基础上再 做重构。 • 对于新功能的重构,应该融入到正常开发过程中,在故 事验收之前已经完成相应的重构,因为自动化测试不是万能 的,也不可能达到100%的覆盖率,所以还是需要QA验证的。 这么做就意味着客户要为我们的重构买单,所以作为软件领域 专家的我们,如何让业务领域专家的客户理解重构的价值,这 就变的至关重要了。 • 小步前进,尽量避免或者减少大的重构,这样可以减少 突然增多的回归测试工作量,也会减少功能被破坏的风险。如 果发生了大的重构,反思一下是哪里出了问题?是我们积攒了 太多的技术债?还是业务领域模型发生了大的改变?然后采取 措施避免类似的事情再度发生。 • 对于一些核心功能或者组件,进行重构之前尽早告知团
27. 队QA,如果能够给QA讲解一下重构的目的以及本次重构可能 会影响到的业务区域会对QA有很大的帮助。这样做一方面可以 让QA把重心放在最容易受到影响的功能上加强回归测试,另一 方面也能帮助QA更合理地安排测试计划。 • 尽量避免在产品上线前进行重构,不仅可以减轻QA回归 测试的负担,也会降低功能破坏后来不及修复的风险。 重构的目标是为了改善代码质量,长远来看应该是可以减 少软件缺陷的,从这个角度来说QA和开发人员的目标是一致 的,我们相信,如果重构恰当,必定对项目是有利无害的。
28. 一个遗留系统自动化测试的七年之痒 文/胡志芳 本文首发于InfoQ: http://www.infoq.com/cn/articles/automation-testof-a-seven-year-legacy-system 背景 项目从2009年开始启动,采用的是TDD开发方式。在这之 后的过程中,团队做过各种尝试去调整自动化测试的策略去更 好地适应不同阶段项目的特征,比如调整不同类型测试的比 例,引入新的测试类型等。 七年之痒——痛点 随着项目走到了第七个年头,一系列的变化在不断发生, 比如技术上引入了微服务、EventStore等,业务变得越来越复 杂,子系统变得更多,更多的人员加入,开始实施按月发布 等,这些因素交织在一起凸显出自动化测试的滞后。首先是从 团队成员感知到的一些痛点开始的: 质量下降——这个体现在部署到测试环境的代码质量较
29. 差,常常就是新版本部署上去之后某个核心功能被破坏,要么 是新功能破坏了老功能,要么是bug的修复把其他功能破坏。 测试不稳定——QA有很长的时间在等待修复或新功能提 交出包,而这个等待可能是几个小时也有可能是几天。除去网 络问题、部署流水线的复杂性等因素,自动化测试的不稳定性 也导致出包的速度也受到了影响。大家往往更关注于怎么能把 测试通过了能够出一个包,却忽略了我们该怎么去处理一个不 稳定的测试。下图的run2, run3正是大家在不断的尝试去rerun 挂掉的测试。 团队越来越忙,开始陷入恶性循环——随着功能的逐渐
30. 增多,每个月上线的回归测试列表越来越长,QA需要花更多的 时间去做重复的回归测试,新功能的测试和回归测试的压力都 很大,甚至有的时候根本都没有时间去review下一个阶段的需 求,更别提其他一些更有价值的事情。往往回归测试做不完就 不得不往下一个阶段推,这种不断往复导致大家对发布的产品 信心严重不足。 在这种情况下,自动化测试的有效性和完备性都受到了质 疑。本来期望自动化测试能够帮助我们构建一张安全的防护 网,保证主干业务不被破坏;随着pipeline频繁地去执行,及时 反馈问题,不要等到测试环境才暴露出来;同时能够把QA重复 的手工测试时间释放出来,去做一些更有价值的事。可是根据 团队所感受到的痛点,我们觉得自动化测试不仅没有帮助到我 们,反而在一定程度上给团队带来了干扰。 问题分析 自动化测试到底出了什么问题?我们从现有UI测试入手开 始分析,发现了以下典型现象: 1.最有价值的场景没有被覆盖 虽然有较多的测试场景,但是体现出核心业务价值的场景 却稀少。我们都知道80/20原则,用户80%的时间在使用系统中 20%的功能,如果大部分的UI测试是在测另外那80%的功能, 这样一个覆盖给团队带来的安全指数是很低的。
31. 2.失效的场景 功能已经发生了变化,可是对应的UI测试并没有变,至于 它为什么没有挂掉,可能有一些侥幸的因素。比如现在点了确 认按钮之后新增了弹窗,而测试并没有关掉弹窗,而是通过 URL跳转到了别的页面,也没有验证弹窗的新功能是否工作, 既有的实现方式确实会使得测试一直通过,但是没有真的验证 到正确的点。 3.重复的测试 同样的测试在UI层跟API层的重合度较高,有的甚至是 100%。比如搜索用户的功能,分别去按照姓、名、姓的一部 分、名的一部分、姓+名等等各种组合去验证。我们不太清楚 在当时是基于怎样的考虑留下了这么多跟UT/API测试重复的用 例,但是在现阶段分析之后我们觉得这是一种没必要的浪费。 另外,不同的测试数据准备都是UI测试执行出来的,很多场景 都用到了相同的步骤,我们觉得这也是一种重复,可以通过其 他方式来实现。 解决问题 这些问题从某种角度上都暴露出了UI测试年久失修,没有 得到好的维护,而新功能的自动化测试又在不断重蹈覆辙,问 题积攒到一起爆发出来使得大家开始重视自动化测试。 有痛点
32. 并且找到问题了,下一步就是解决问题。我们分了两步来走, 第一个就是对已有UI测试的优化,第二个是对新功能的自动化 测试策略的调整。 已有UI测试的优化 针对已有的自动化测试,再回过头逐个去审查UT/API/UI测 试代价太高,我们只能是从UI测试优化入手。针对前面提到的3 个问题我们逐一去攻克: • 识别系统关键业务场景 我们首先挖掘出系统中用户要达到的各个业务目标,根据 不同的业务目标梳理出不同的业务场景,然后将这些发给客户 去评审。客户对我们总结出的这些场景很认可,只是把每个业 务目标都赋予了一个优先级,为后续的编码实现给予了参考。 • 重新设计测试场景 UI测试不是着重去测试某个功能是否工作,更关注的是用 户在使用系统时能否顺利实现某个业务目标,因此我们需要知 道用户是怎么使用系统的。同样的目标,可能会有多个途径来 完成,通过跟客户的访谈以及观察产品环境下页面的访问频 度,我们重新规划了测试场景,期待能更贴近用户的真实行 为,及时防御可能会导致用户不能顺利完成业务目标的问题。
33. • 优化测试数据准备,删除重复的测试 对于UI层的过度测试,直接删除和API/UT层重复的测试, 保留一条主干路径用来测试系统连通性。 对于不同的业务场景 可能需要准备的数据,我们舍弃了之前通过UI执行测试这种成 本高的方式,转而以发API请求的方式来准备,这样降低了测 试执行的时间,也使得测试更加的稳定。 重新梳理的测试场景 帮我们构建了一张较为全面的安全防护网,覆盖了绝大部分的 用户使用场景,大家的信心显著提高。如果核心业务受到破 坏,立马就可以通过UI测试反馈给相关的人。执行更加稳定的 测试也减少了大家对UI测试是否能真的发现问题的质疑,因为 随机挂的频率大大地降低,一旦挂可能就是真的有bug了。 新功能自动化测试策略的调整 我们一般会以测试金字塔作为自动化测试的指导策略,下 图是我们项目的测试金字塔。
34. 为了避免新功能步旧功能的后尘,我们对自动化测试策略 进行了调整。除去以不同层的数量分布来判定策略是否合理 外,我们也更看重在这个数量下关键业务场景是否能被有效地 覆盖,主要通过下面两种方式来保证: 1.QA及早介入自动化测试 质量是需要内建的,不是测出来的。QA从一开始就介入整 个流程之中,在story启动的时候会和DEV一起准备任务拆分。 在后期验收story的同时也会验收单元测试,确保能在 UT/API/Contract层实现的测试都在这些层面覆盖,不仅保证了 底层测试的数量要够多,也确保了这么多测试覆盖的点都是合
35. 理有效的。在这个过程中,QA把更多的测试思路传递给团队成 员,引发大家更多地从质量角度去思考。 2.QA与DEV结对写UI测试 最后在整个功能做完的时候,QA也会和DEV结对实现UI测 试,涉及现有测试场景的维护与更新。基于前面对底层测试的 review,大家对于整个功能的测试覆盖都有了一定程度的了 解,对于UI测试要测得点也会较快的达成一致。另外,QA在与 DEV结对实现UI测试的时候,编码能力也得到了提高。 在推动QA更多参与底层测试的过程中,我们更多地从测试 角度去影响团队,增加了团队的质量意识。QA的时间被释放出 来了,去做了更多有价值的事,比如探索性测试,Log监控与 分析,安全测试,产品环境下用户行为分析等。这一系列活动 的影响就是产品的质量顺便得到了提升。 总结 等我们把已有功能UI测试优化完,新功能的自动化测试策 略开始落实到全组,已经是半年以后的事了。我们慢慢地感受 到一切都在回归正轨,之前的痛点在逐步消去,团队交付的节 奏也越来越顺畅,对发布产品的信心也更强了。 回顾这个遗留系统的自动化测试优化过程,我们有一些 收获: 1.大家说到UI测试往往更倾向于如何编码实现,但我们希
36. 望开始UI测试的时候能多关注下测试用例的设计是否合理,是 不是能够体现出业务价值。 2.UI测试的用例和代码都是测试资产,需要跟产品代码等 同对待,不能写出来就不管不顾,没有维护是不可取的。 3.自动化测试不仅仅是UI测试,需要和UT/API等其他底层 测试一起分工合作,作为测试策略的一部分来为产品质量保驾 护航。
37. 测试自动化后,我们需要怎样的 QA? 文/邱俊涛 我们先讨论一下在传统的瀑布模型下QA是如何工作的,其 中最主要的问题是什么;然后作为对比,我们再来看看敏捷团 队里的QA是如何工作的,工作重点又是什么;最后,我们详细 看一看在新的职责下,QA应该如何做。 瀑布开发模型 即使在今天,在很多企业中瀑布模型仍然是主流。每一个 需求都需要经过分析、设计、开发、测试、上线部署、运维等 阶段。虽然一些企业已经开始实施敏捷开发,比如项目/产品以 迭代的方式运作,也有诸如每日站会、代码检视等敏捷实践, 但是如果仔细审视,你会发现其实开发模式从骨子里来说还是 瀑布:按照软件组件划分的部门结构(详见康威定律)、按照 职能划分的团队(开发和测试分属不同部门)、过长的反馈周 期、永远无法摆脱的集成难题等等。 随着软件变得越来越复杂,团队里没有任何一个人可以说 出系统是如何运作的,也不知道最终用户是谁,以及最终用户 会以何种方式来使用最终的软件。
38. 更糟糕的是,按照职能划分的团队在物理上都是隔离的, 比如独立的测试部门、独立的运维部门、整日忙碌而难以预约 到档期的业务人员,当然还有经常疲于交付、无处吐槽的开 发。由于这些隔离,信息的反馈周期会非常长,一个本来很容 易修复的缺陷可能在4周之后才会被另一个部门的测试发现, 然后通过复杂的工作流(比如某种形式的缺陷追踪系统)流到 开发那里,而开发可能还在拼命地完成早就应该交付的功能, 从而形成恶性循环。 瀑布模式中的QA 在这样的环境中,QA们能做的事情非常有限。在需求开始 时他们会参加需求澄清的会议,制定一些测试计划,然后进行 测试用例的设计。有的企业会用诸如Excel之类的工具来记录这 些用例。这些写在Excel里的“死”的用例作用非常有限。而最大 的问题在于:它们无法自动化执行。另外,在实际软件开发 中,需求会经常发生变化,需求的优先级也会有调整,然后这 些记录在Excel中的“死”的用例会很快过期,变得无人问津。 除此之外,QA中的有些成员会使用工具来录制一些UI测试 的场景,然后在每个新版本出来之后进行回放。然而,当UI发 生一点变化之后,这些自动化的用例就会失效:比如HTML片 段中元素位置的调整,JavaScript的异步调用超时等等。 显然,这种单纯以黑盒形式来检查功能点的测试方式是不
39. 起效的,要真正有效的提升软件质量,仅仅通过事后检查远远 不够,软件的质量也应该内建于软件之中。QA的工作也应该是 一个贯穿软件生命周期的活动,从商业想法到真实上线,这其 中的所有环节都应该有QA的参与。 系统思考 如果不从一个系统的角度来思考软件质量,就无法真正构 建出健壮的、让业务和团队都有信心的软件系统。质量从来都 不只是QA的职责,而是整个团队的职责。 关于软件质量,一个根深蒂固的误解是:缺陷在开发过程 中被引入,然后在测试阶段被发现,最后在QA和开发的来回撕 扯中被解决(或者数量被大规模降低),最后在生产环境中, 就只会有很少的、优先级很低的缺陷。 然而事实上,很多需求从开始就没有被仔细分析,业务价 值不很确定,验收条件模糊,流入开发后又会引入一些代码级 别的错误,以及业务规则上的缺陷,测试阶段会漏掉一些功能 点,上线之后更是问题百出(网络故障、缓存失效、黑客攻 击、操作系统补丁、甚至内存溢出、log文件将磁盘写满等 等)。 在一个敏捷团队中,每个人都应该对质量负责,而QA则以 自己的丰富经验和独特视角来发掘系统中可能的质量隐患,并 帮助团队将这些隐患消除。
40. ThoughtWorks的Anand Bagmar在他的演讲What is Agile testing- How does automation help?中详细讨论过这部分内容。 QA到底应该干什么? 本质上来说,任何软件项目的目标都应该是:更快地将高 质量的软件从想法变成产品。 将这个大目标细分一下,会得到这样几个子项,即企业需 要: • 更大的商业回报(发掘业务价值) • 更短的上线时间(做最简单,直接的版本)
41. • 更好的软件质量(质量内嵌) • 更少的资源投入(减少浪费) 其实就是传说中的多、快、好、省。如果说这是每一个软 件项目的目标的话,那么团队里的每一个人都应该向着这个目 标而努力,任何其他形式的工作都可以归类为“浪费”。用Excel 记录那些经常会失效,而且无法自动执行的测试用例是浪费, 会因为页面布局变化而大面积失效的UI测试也是浪费,一个容 易修复的缺陷要等到数周之后才被发现也是浪费。 在这个大前提下,我们再来思考QA在团队里应该做什么以 及怎么做。 QA的职责 Lisa Crispin在《敏捷软件测试》中提到过一个很著名的模 型:敏捷测试四象限。这个模型是QA制定测试策略时的一个重 要参考:
42. 如果按照纵向划分的话,图中的活动,越向上越面向业 务;越向下越靠近技术。横向划分的话,往左是支撑团队,往 右是评价产品。 其实简化一下,QA在团队里的工作,可以分为两大类: • 确保我们在正确的交付产品 • 确保我们交付了正确的产品 根据这个四象限的划分,大部分团队可能都会从Q2起步: QA会和BA,甚至UX一起,从需求分析入手,继而进行业务场 景梳理,这时候没有具体的可以被测试的软件代码。不过这并 不妨碍测试活动,比如一些纸上原型的设计:
43. 这一阶段之后,我们已经有了用户故事,这时候QA需要和 开发一起编写用户故事的自动化验收测试。当开发交付一部分 功能之后,QA就可以做常规的用户故事测试了,几个迭代之 后,QA开始进行跨功能需求测试和探索性测试等。根据探索性 测试的结果,QA可能会调整测试策略,调整测试优先级,完善 测试用例等等。 根据项目的不同,团队可以从不同的象限开始测试策略的 制定。事实上,Q1-Q4仅仅是一个编号,与时间、阶段并无关 系,Lisa Crispin还专门撰文解释过。 关于QA如何在软件分析的上游介入,并通过BDD的方式与 业务分析师一起产出软件的各种规格描述,继而通过实例来帮 助整个团队对需求的理解,ThoughtWorks的林冰玉有一篇文章
44. 很好地介绍了BDD的正确做法。如果将QA的外延扩展到在线的 生产环境,制定合理的测量指标,调整测试策略,强烈推荐林 冰玉写的另一篇文章产品环境中的QA。 其他职责 事实上,软件生命周期中有很多的活动处于灰色地段。既 可以说是应该开发做,又可以说应该QA做,甚至可以推给其他 角色(比如OPs)。不过我们知道,一旦涉及角色,人们就再 也不会按照全局优化的思路来应对问题了。这种灰色的活动包 括: • 持续集成的搭建 • 测试环境的创建与维护 • UAT上的数据准备 • 代码中的测试代码的维护 • 测试代码的重构 在团队实践中,这些活动我们通常会让QA和开发或者OPs 同事一起结对来完成。一方面避免知识孤岛的形成,另一方面 在跨角色的工作中,也可以激发出更多不同的思路。 万能的QA? 虽然在这些活动中,QA都会参与,但并不是说团队里只要 有一个QA就可以了。QA在参与这些活动时,侧重点还是有很
45. 大不同的。 比如需求分析阶段,如果有QA的加入,一些从QA角度可 以发现的有明显缺陷的场景,则可以在分析阶段就得到很好的 处理。另一方面,尽早介入可以设计出更合理的测试计划(比 如哪些功能的优先级比较高,用户会更频繁使用,那么对应的 测试比重也会更高)。在Story分析与书写阶段,QA可以帮助 写出更加合理的验收条件,既满足业务需求,又可以很好的指 导开发。 在和开发一起编写澄清需求时,主要是编写自动化验收测 试,而不是实际编写业务逻辑的实现(虽然QA应该参与Code Reivew环节,学习并分享自己的观点);甚至在上线运维阶 段,QA还需要和OPs一起来设计用户数据的采集指标(比如用 户访问的关键路径,浏览器版本,地区的区分等),从而制定 出新的测试策略。 扩展阅读 • What is Agile testing – How does automation help? • 敏捷实践Showcase的七宗罪 • 产品环境下的QA • 《敏捷软件测试》
46. 从测试策略到测试架构 文/刘冉 今年(2017年)是我做软件测试的第7个年头了,当年我 从软件开发转做软件测试的时候,没有想过我能在这个领域做 这么久。 在这7年里面,我在软件测试领域摸爬滚打,从自动测试 起步,逐步接触到软件测试的各个领域:各种测试方法(等价 类,全配对等)、测试技术(单元测试,功能测试,性能测 试,探索性测试等)、自动化测试工具(JUnit,Selenium, Gatling,ZAP等)、测试流程(传统测试流程,敏捷测试流程 等)以及测试策略(测试象限和测试金字塔等)。 其中“测试策略”在测试业界是讨论的比较少的,因为大多 数人的工作重点是设计测试用例,执行测试或者开发和维护自 动化测试,而只有少部分人才会涉及测试策略的工作,从而导 致很多测试人员其实并没有系统的了解测试策略。 所以我准备将我这几年对于测试策略的经验、总结以及思 考以系列文章的形式写出来,希望能稍微帮助一下大家去理解 测试策略,从而做到更好的测试,减少缺陷,提高质量。 测试策略
47. 首先来看一下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)的第一目标就是“减少缺陷 的出现和发布”。其中“减少缺陷的出现”可以通过测试前移等方 法来解决,在进行软件需求分析和架构设计的时候发现缺陷; 而“减少缺陷发布”可以使用各种测试方法、技术来验证和测试 编码完成的功能(这两点在今后的文章里面会通过不同的例子
48. 进行更详细的阐述)。 由此可见,“测试策略”并不是只由测试人员定制的,它是 由一个团队的各个角色一起来制定和建立的,目的是保证软件 的质量,减少缺陷。 而“测试计划”是用于实施测试策略的。只有充分理解测试 策略目的和实施方式,才能充分理解测试策略,为什么要做测 试策略,什么样的测试策略才更有意义、更好,怎样实施才能 更有效等问题。 测试计划 测试计划在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 制定测试计划是保证测试策略能被有效执行的一种方式。 它告诉了团队在什么阶段,什么样的角色应该执行测试策略中 什么样测试技术和测试方法。它主要由测试人员编写,但是应 该由整个团队进行评审,因为开发人员、产品经理、业务分析 人员甚至用户都可能参与到测试计划的执行中。
49. 测试计划是可以根据项目的实际进展情况进行调整的,所 以它并不是一成不变的。 测试架构 在上个世纪六七十年代软件系统还处于小规模的时候,软 件开发并没有谈什么架构,软件测试也不存在什么策略可言。 但是随着软件规模的极速增大,复杂性也成指数级增加,专业 的软件架构应运而生。 为了有效地在规定时间内完成复杂软件系统的测试,必须 有一个指导性的策略来帮助团队理解、选择和组织大量的测 试,因此软件测试策略就出现了。而测试策略往往是高层次的 指导,对于一些中小型项目也许已经足够了,但是却不足以应 付现代越来越复杂的软件系统。 因为随着微服务、移动互联网、物联网、大数据分析系 统、AI系统等的出现,要测试一个包含各种技术,外部依赖, 或者独立子系统的复杂系统,并不是简单的根据测试策略在不 同层面上做不同的测试就可以了,而是要理清各种测试之间的 相互联系和制约,然后思考怎么有效地将各个维度上的测试联 系起来,以软件系统架构的思维去思考整个测试体系。 请注意这里不是说要去设计一套全自动化的测试系统来完 成整个系统的所有测试,而是通各种有效的方式(无论手动还 是自动)把各种测试合理且有效地联系起来,形成一个拥有完
50. 整架构的测试体系,这样才能使整个系统的各种测试更加可视 化和更易于理解,使整个系统的各种测试更加有效,避免重复 测试,节约成本。 举例来说,一个前后端分离的Web业务系统不仅有前端UI 和大量的JavaScirpt代码,还有后端的API和第三方依赖系统以 及数据库系统,如何将各层测试有效地联系起来就是测试架构 需要解决的问题。 首先,前端、后端API、第三方依赖系统和数据库系统有 各自的单元测试、集成测试等,然后可以使用契约测试来测试 统一前端和后端API,再使用Stub加入对于第三方依赖系统的契 约测试或者监控测试,还需要使用测试数据生成系统参数,将 各种测试数据存入数据库系统用于支持契约测试等。
51. 对于不同软件系统,其架构一般都是根据业务需求、技术 能力等各种条件来设计的。与软件架构一样,测试策略和测试 架构在不同的项目里面,需要根据其软件系统的架构、技术 栈、业务需求、人员的技能等因素来定制和设计。 再谈测试策略 现在业界流行的测试金字塔和测试象限只是两种高度抽象 和简化的测试策略模型,不具备实际可操作性,只具备高层次 的指导性和参考性。直接根据这两个模型来工作是低效的,甚 至可能带来负面效果。所以对于测试金字塔和测试象限不能盲 目地使用,而是需要根据项目的实际情况来生成适合自己项目 的测试策略和测试架构,并在此基础上执行真实的测试工作。
53. 说起 BDD,你会想到什么? 文/林冰玉 在刚接触BDD(Behavior Driven Development,行为驱动开 发)的时候,我以为就是用Cucumber这样的工具来编写场景用 例,从而实现自动化测试,甚至很长时间分不清BDD和 ATDD(Acceptance test driven development)到底有什么区别。那 么,BDD真的就是用来做自动化测试的吗?本文就来跟大家分 享一下我理解的BDD。 为什么要BDD? “开发软件系统最困难的部分就是准确说明开发什么”(“The hardest single part of building a software system is deciding precisely what to build” ——No Silver Bullet, Fred Brooks) 。 场景一:业务分析人员觉得自己分析的需求已经写得很清 晰了,并且跟技术人员进行了足够的沟通,可是开发完sign off 的时候,发现所开发的功能还是跟期望有差距。 场景二:开发团队辛辛苦苦开发完一个功能,满怀信心地 去给客户展示的时候,才发现原来客户需求的功能不是这样 的。 这些场景是不是似曾相识?为什么会这样?第一个场景是
54. 开发团队内部技术人员跟需求分析人员的理解有偏差,导致大 家理解的需求其实是不一样的;第二个场景是开发团队没有真 正理解产品经理/客户所提出来的真实需求,导致开发的产品跟 需求不一致。其实,产生这两个不一致的真正原因是因为不同 角色有着不同的领域知识,说着不同的语言,大家在沟通的时 候,如果都用自己的领域语言,必然会产生沟通代沟,导致理 解的不一致性。 领域知识不同、语言不通导致沟通障碍,这个客观存在的 问题该如何解决呢?BDD正是为此而生。 BDD是什么? BDD的提出者Dan North强调BDD不是关于测试的,它是在 应用程序存在之前,写出用例与期望,从而描述应用程序的行 为,并且促使在项目中的人们彼此互相沟通。 要给BDD下个清晰易懂的定义很难,包括大师们也这么认 为,这里试着总结以下几点: 1.关注的是业务领域,而不是技术:BDD强调用领域特定 语言(DSL, domain specific language)描述用户行为,定义业 务需求,而不会关心系统的技术实现。 2.不是工具,强调的是一种协作方式:BDD要求各个角色 共同参与系统行为的挖掘和定义,以实现对业务价值的一致理 解。
55. 3.不是关于测试的:BDD源自TDD,但重点不是关于测 试,所强调的沟通与协作可以指导更好地做自动化测试。 4.全栈敏捷方法:BDD促使团队所有角色从需求到最后的 测试验证,进行高度的协作和沟通,以交付最有价值的功能。 BDD怎么做? 用例场景的描述格式“GIVEN…WHEN…THEN…”对大家都 不陌生,但用这个格式写出好的用例却是非常的难,尤其是新 手。这里总结几点供大家参考: 1.业务层抽取,业务语言描述 根据业务层的数据流,在每个数据停留点进行纵切,抽取 出一个个用例场景。描述语言一定是业务领域可懂的,不要涉 及任何实现相关的技术细节。所描述的场景一定是从业务层抽 象出来,体现真实业务价值的。 2.技术人员可懂,自动化友好 所描述的用例场景要能驱动开发,必须要让技术人员易于 理解;要指导自动化测试,还得要求对于自动化的实现是友好 的。这一点似乎是跟第一点有些矛盾,但我们严格遵守BDD的 格式要求还是可以做到的。其中,GIVEN从句描述的是场景的
56. 前提条件、初始状态,通常是一种现在完成时态;WHEN从句 是采取某个动作或者是发生某个事件,一定是动词,通常是一 般现在时;THEN从句用“应该…(should be…)”来描述一种期望 的结果,而不用断言(assert),后者与测试关联更紧密。 3.数据驱动,需求实例化 抽象的业务语言描述的需求,往往由于太抽象而缺失掉很 多关键信息,导致不同人员对需求理解的不一致。想要既抽象 又能包含细节信息,就需要采用需求实例来描述。简单说来, 就是给场景用例举例说明。举例就会需要列举数据,如果在场 景用例描述里边直接添加数据实例,那样的用例将会很混乱, 可读性和可维护性都非常差。如果我们能够在描述场景的用例 里边用一些变量来代替,把变量对应的值(数据)提取出来存 为一个表格或者独立的文件,这样将会使得用例的可读性很 好,而且也不会缺失细节信息(数据),后期的维护和修改也 较为方便。这就是数据驱动的方法来描述实例化的需求。 看几个例子,大家体会一下: 场景一:检查收件箱,可以看出第三个清晰明了且能体 现业务价值,比较符合上面的要求。 Scenario: Check Inbox
57. Given a user "Tom" with password "123" And a user "Jerry" with password "abc" And an email to "Tom" from "Jerry" When I sign in as "Tom" with password "123" Then I should see one email from "Jerry" in my inbox Scenario: Check Inbox Given a user "Tom" And a user "Jerry" And an email to "Tom" from "Jerry" When I sign in as "Tom" Then I should see one email from "Jerry" in my inbox Scenario: Check Inbox Given I have received an email from "Jerry" When I sign in Then I should see one email from "Jerry" in my inbox 场景二:限制非法用户查看某些受限内容,BDD强调什 么(What)、而不是怎么(How),第二个写的比较好。 Scenario: Redirect user to originally
58. requested page after logging in Given a user "Tom" exists with password "123" And I am not logged in When I navigate to the home page Then I am redirected to the login form When I fill in "Username" with "tom" And I fill in "Password" with "123" And I press "Login" Then I should be on the home page Scenario: Redirect user to originally requested page after logging in Given I am an unauthenticated user When I attempt to view some restricted content Then I am shown a login form When I authenticate with valid credentials Then I should be shown the restricted content 场景三:添加图书到购物车并计算总额 Scenario: Books add to shopping cart with correct number and total price Given a book "BDD" with price "30.5" And a book "Cucumber" with price "25.8"
59. When I select "BDD" And I click the add to shopping cart button Then I should see one "BDD" in my shopping cart And the total price is "30.5" When I select "Cucumber" And I click the add to shopping cart button twice Then I should see two books "Cucumber" in my shopping cart And the total price is "82.1" Scenario Outline: Books add to shopping cart with correct number and total price Given book with And book with When I add book and book to shopping cart Then I should see book and in my shopping cart And the total price should be Examples: name1 price1 number1 name2 price2 number2 total BDD 30.5 1 - -
60. - 30.5 Cucumber 25.8 - 51.6 - - BDD 25.8 2 2 30.5 82.1 1 Cucumber BDD的工具有Cucumber、JBehave、Twist、Concordion等, 工具的优缺点和使用方法,网上都有丰富的文档可参考,在此 不作介绍。 BDD有什么好处? BDD的作用是把利益关系人、交付团队等不同方面的项目 相关人员集中到一起,形成共同的理解,共同的价值观以及共 同的期望值。它可以帮助我们: • 关注用户行为 • 交付最有用的功能 • 在团队内部维护一致的术语 • 探究需求实例 • 编写和维护需求 • 创建活的文档 • 消除协作与沟通障碍 什么样的项目适合BDD?
61. • 简单的一次性项目,沟通交流成本都较低的情况下,没 有必要使用BDD; 业务比较轻量,重在技术方面的项目,可以只使用 • TDD,或者简单的白板上的BDD,不需要在BDD工具记录需求 用例文档; • 业务复杂、团队成员较多的项目,沟通成本高,BDD很 有必要。 常见疑惑 1.BDD与TDD/ATDD TDD是测试驱动开发,ATDD是验收测试驱动开发,都是 关于测试的,是与所开发的系统紧密联系的。而BDD则不同, 前面提到过BDD不是关于测试的,着重关注需求、关注客户的 业务价值,所描述的需求用例是可以独立于软件系统存在的, 因为客户的业务是始终存在的,不取决于是否有软件系统来支 撑。 2.BDD与SBE SBE(Specification By Example,实例化需求)是在BDD之后 由Gojko提出来的,也是关于需求的,主要强调通过列举实例发 现需求中的缺失概念。BDD也是关注需求的,同样会使用实例
62. 来描述行为。两者的本质没有区别,只是概念的差异。
63. 醒醒吧少年,只用Cucumber不能帮 助你BDD 文/毛超 引言 在Ruby社区中,测试和BDD一直是被热议的话题,不管是 单元测试、集成测试还是功能测试,你总能找到能帮助你的工 具,Cucumber就是被广泛使用的工具之一。许多团队选择 Cucumber的原因是“团队要BDD”,也就是行为驱动开发 (Behavior Driven Development),难道用了Cucumber之后团队就 真的BDD了么? 事情当然没这么简单了,BDD作为一种软件开发方法论, 一定要理解其含义并且遵循特定的流程,工具只不过是起辅助 作用而已。会切菜的不一定都是厨子,会写代码的不一定都是 程序员。Cucumber的作者Aslak也在博客中提到:“在BDD出现 的9年后,依然有不少团队在使用BDD时出现问题……BDD依 然经常被人误解成单纯的测试,或者是一个可以被下载的工 具。” 同时,Aslak也吐槽了Cucumber目前的处境:“就在最近, Cucumber已经被下载了超过500万次,我很高兴它如此受欢
64. 迎,同时也为它被广泛的误用而感到失望……Cucumber有时依 然被错误地当成自动化测试工具,而不是我当时创建的东西。” 那么问题来了,怎样在日常项目中使用Cucumber呢?真的 能在日常项目中进行BDD开发么?要回答这个问题,我们需要 重新认识一下BDD。 BDD的提出 2003年,开发人员Dan North偶然间发现把测试的标题经过 简单的文字处理可以更好表达代码蕴含的业务逻辑,比如下面 这段代码: public class CustomerLookupTest extends TestCase { testFindsCustomerById() { ... } testFailsForDuplicateCustomers() { ... } } 当我们把测试方法中的test去掉,给单词加上空格,然后把
65. 他们组合在一起时,就会出现: CustomerLookup - finds customer by id - fails for duplicate customers - ... 在Dan看来,这无疑是对CustomerLookup类的描述,并且是 用测试内容来描述代码中类的行为。Dan发现他似乎找到了一 种方式,可以在TDD的基础上,通过测试来表达代码的行为。 在尝到甜头后,Dan写了JBehave,用一个更关注代码行为的工 具来代替JUnit进行软件开发。经过一番折腾后,Dan觉得只描 述类行为不过瘾,便开始把关注点从类扩展到整个软件,他和 当时项目组的业务人员一起把需求转化成Given/When/Then的三 段式,然后用JBehave写成测试来描述软件的某种行为。当测试 完成后,开发人员才开始编码,一旦测试通过,那软件就完成 了测试中描述的某种行为。在他看来,他把TDD升级了,因为 他不再只关注于局部类的方法,而开始关注整个软件的行为。 通过这种方式,Dan成功地把需求转换成了软件的功能测 试,先写功能测试再驱动出产品代码,保证软件行为正确性。 其次,Dan强调在测试中要尽可能地使用业务词汇,保证团队 成员对业务理解一致。于是,BDD就此诞生。
66. BDD不只是自动化测试 在上面的故事中,“测试”这个词出现了很多次,你是不是 已经认为BDD就是用功能测试驱动产品代码的开发流程呢?其 实不然,功能测试只是一个结果而已,更重要的是和业务人员 一起分析需求,沟通交流来产生测试的过程。用测试驱动出来 的代码可以保证是正确的,但如何保证测试是正确的呢?答案 就是人,通过业务,开发和测试一起参与生成的测试文档,不 仅能保证软件功能上是正确的,还能保证团队成员对业务理解 是一致的。在测试文档中,也应该尽量保证使用自然语言和业
67. 务词汇,减少非技术人员的学习成本。 在多年之后,Dan也终于给出了他对BDD的定义:“BDD是 第二代的、由外及内的、基于拉(Pull)的、多方利益相关者的 (Stakeholder)、多种可扩展的、高自动化的敏捷方法。它描述了 一个交互循环,可以具有带有良好定义的输出(即工作中交付 的结果):已测试过的软件。” Cucumber的另一位作者Matt Wynne也给出了自己的定 义:“BDD的实践者们通过沟通交流,具体的示例和自动化测 试帮助他们更好地探索、发现、定义并驱动出人们真正想用的 软件。” 从上述定义我们可以看出,BDD更强调流程和一系列实 践,自动化测试只是其中一部分而已。 Cucumber到底怎么用 理解了BDD的精髓后,我们就不难找出正确的使用 Cucumber的方式了。根据Cucumber的定义,它的核心就是 Specification,其实就是文档化的需求。Specification是通过 Requrement Workshop生成的,在Workshop中,业务、开发和测 试一起分析需求,把需求用自然语言写成文档,然后再转换成 Given/When/Then的Specification文件,这样便完成了BDD中最 重要的一步--定义软件正确的行为。接着开发人员开始编 码,完成相应需求,保证Specification文件运行通过,整个流程
68. 结束。 简单来说,Cucumber其实不是一个自动化测试工具,而是 一个促进团队沟通合作的工具。但由于Cucumber无法确保上述 流程真正的发生,有很多团队简化或者跳过了Workshop,直接 开始写Specification文件,没有沟通就很难保证理解一致,Bug 也许就在那时潜伏了下来。这样大家也就不难理解作者吐槽 的“Cucumber被广泛地误用”,其实Cucumber只是一个沟通工 具,它只是刚巧可以运行测试而已。 理想很丰满,现实很骨感
69. 任何工具和实践都有优缺点,Cucumber也不例外。团队在 开始尝试新的实践或者工具时,多多少少都会碰到一些问题, 下面我们就来看看一些使用Cucumber的问题。 没有业务人员参与的Specification 要么业务人员没时间写Specification,交给其他人写,写完 之后业务人员也没时间去审核。在这种情况下,很难保证 Specification的业务正确性,一旦Specification出现问题,团队 可能出现理解不一致、甚至做错需求的现象。反过来看, Specification文件由自然语言而不是代码组成,也能反映出对非 技术人员参与的重视程度。然而现实情况很难保证业务、测 试、开发有充足的时间进行Specification的讨论和编写,这也是 导致业务人员逐渐脱离Specification的主要原因。 Specification关注实现细节而不是业务逻辑 Cucumber使用自然语言描述业务需求,然而不少团队都陷 入到了实现细节中。比如: Scenario: Detect agent type based on contract number Given I am on the 'Find me' page
70. And I have entered a contract number When I click 'Continue' button And a contact number match is found Then the "Back" button will be displayed 上面的描述满篇是点击了哪个按钮,输入了什么内容,看 完之后反而让人有点困惑,用户到底为什么要做这些,做了之 后有什么价值。这样的Specification既不能满足团队成员对业务 需求的了解,也会由于界面的细微改动运行失败。 Step的嵌套调用 Specification文件由Step组成,在Step中我们可以通过Ruby 进行自动化的页面操作。有时我们会发现某些Specification会重 复进行一系列的操作,这时我们就可以把重复的Step进行组 合,创建出新的Step。比如这样 Given there is student Harry And there is professor Snape And student Harry joins class of professor Snape # use 1 new step instead of 3
71. Given student Harry in class of professor Snape 那么这个新的Step该怎么实现呢?Cucumber支持在Step中 调用Step,比如这样: Given /^student (.*) in class of professor (.*)/ do student, professor step "there is student #{student}" step "there is professor #{professor}" step "student #{student} joins class of professor #{professor}" end 乍一看好像没什么问题,其实不然。Step使用正则表达式 进行匹配,问题恰恰出在正则上。 首先,正则灵活性很大,你确定上面例子中step “there is student #{student}”一定会调用到你想要调用的Step么?你无法确 定在运行时,是否会出现另一个Step“there is student come from China”来截胡。 其次,正则逆推难度很大,也就是说当你看到“^(25[05] 2[0-4][0-9] [0-1]{1}[0-9]{2} [1-9]{1}[0-9]{1} [1-9]).(25[05] 2[0-4][0-9] [0-1]{1}[0-9]{2} [1-9]{1}[0-9]{1} [1-9] 0).(25[0-
72. 5] 2[0-4][0-9] [0-1]{1}[0-9]{2} [1-9]{1}[0-9]{1} [1-9] 0).(25[05] 2[0-4][0-9] [0-1]{1}[0-9]{2} [1-9]{1}[0-9]{1} [0-9])$”时,你 很难看出这是在匹配IP地址。所以当我们需要修改step时,很难 确定有多少个step在依赖它,这也加大了维护成本。 最后,嵌套次数过多的Step也会导致代码复杂,难以理 解。 Specification Report可读性不高 Specification除了是自动化测试的描述文件之外,更重要的 是它是软件的“活文档”。有时我们需要通过“活文档”进行知识 传递。Cucumber虽然提供生成Report的功能,但效果未免有些 差强人意。比如下面:
73. 满篇绿色的Step,再加上Given/When/Then来捣乱,这样的 Report只是运行结果而已,可读性很差,很难当成软件需求文 档。究其原因,主要因为Cucumber Report的表现力差。 首先,它只支持纯文本,在这个“一图胜千言,无图无真 相”的时代很难只通过文字来描述复杂业务,如果能在文档中加 上图片,甚至一段视频,都会帮助我们更容易的理解复杂业 务。比如像下面这样的。 其次,Cucumber Report关注的更多是Step,而不是软件需 求。当我们想到软件文档或者手册时,我们脑海中想到的更多
74. 是像教科书一样的文档,内容之间有层级和关联关系,每个功 能有重点和概要内容,更偏向自然语言,而不是简单地把 Specification堆在一起,满篇的Given/When/Then。在现实情况 下,这样的Cucumber Report也难免没有人愿意阅读了。 改进措施 遇到上面的问题不要怕,我们只要理解问题本质,找到对 策解决它,依然可以帮助我们更好地完成任务。下面我们就来 尝试解决一下上面提到的三个问题。 让业务人员写/审查Specification 对于上面的关注细节的例子,如果我们换一个思路,不去 考虑UI之类的东西,就会得出更精炼的Specification。比如下面 Scenario: Customer has a tied agent policy so last name is required Given I have a "TiedAgent" policy When I submit my policy number Then I should be asked for my last name 这样的Specification不再关注按钮,而关注具体的业务需
75. 求,这样就把细节的UI操作推向了Cucumber Step的实现中。这 样可以更直接的展现需求,避免细节内容的干扰。如果情况允 许,我更支持让业务人员写Specification,或者最起码也要审查 Specification文件。通常业务人员是团队中最不懂技术的,这反 而是他们的优势,可以把Specification变得更加面向需求,更加 通俗易懂。 Step实现代码的重用 我们可以通过重构Step实现代码来进行有效的重用,比如 下面 Given /^there is student (.*)/ do student ModelFactory.create_user(student) end Given /^there is professor (.*)/ do professor ModelFactory.create_user(professor) end Given /^student (.*) joins class of professor (.*)/ do student, professor ModelFactory.join_class(student, professor) end
76. 通过重构,我们抽象出ModelFactory进行相关数据准备, 然后就可以重用ModelFactory实现新的Step Given /^student (.*) in class of professor (.*)/ do student, professor ModelFactory.create_user(student, professor) ModelFactory.join_class(student, professor) end 重用代码而不是重用Step,这样不仅可以让Step的实现代 码更加简洁,同时也避免了Step的嵌套调用。 扩展Cucumber生成高质量的文档 Cucumber虽然自带不少种格式的Report,但都不能称其为 真正的文档。不过我们可以通过扩展Cucumber来生成高质量的 文档。 首先,我们可以使用Capybara在对某个正在执行的Step进 行截图。Capybara提供的截图功能可以保留当前Step的运行状 态,通过图片更容易理解当时的上下文,这些图片拼在一起, 其实就是一个完整的用户操作流程。 其次,我们可以通过给Step添加详细描述来解决Report不给
77. 力的问题。我们可以给每一个Specification文件创建一个相对应 的描述文件,描述文件由两部分组成,一部分是Step的标题, 另一部分是详细描述Step的内容。只要通过文本匹配就可以找 到某个Step的详细描述,再加上之前对Step的截图,拼在一起 就可以生成一个高质量的文档了。 举个例子,如果我们有这样一个Specification文件 Scenario: Customer has a tied agent policy so last name is required Given I have a "TiedAgent" policy When I submit my policy number Then I should be asked for my last name 创建一个对应的描述文件,文件类型是Markdown。 ===================== Given I have a "TiedAgent" policy ===================== ##Detail Information** **In this step, you are assigned a "TieAgent" policy.** ![screenshot-1](./i-have-a-tied-agent-
78. policy.png) You can click [here](http://example.com) for more information ===================== .... 在上面的文件中,第一部分是Step标题,用来匹配 Specification文件中的Step,第二部分是Markdown类型的片段, 里面有图片、超链接等富文本元素,可以更好地帮助我们理解 业务。 最后,通过Cucumber中提供的AfterStep Hook完成文档的生 成。比如这样 AfterStep('@active-doc') do scenario @step = 0 @doc = ActiveDocument.new @doc.generate(scenario, scenario.steps[@step].name) @step += 1 end 代码中的ActiveDocument是自己实现的,它把丰富的HTML
79. 内容和截图整合在一起,然后把Specification中所有的Step拼接 在一起,就生成了一个Specification的文档。这样的文档相比之 前提到的Cucumber Report具有更高的可读性,同时也具有更强 的灵活性,因为文档是通过HTML展现的,我们可以添加更多 的内容,比如Specification文档之间的跳转链接,或者提前录制 的一段视频放入文档中,甚至可以加上第三方css和js库让文档 变得更加引人入胜。 原来生活可以更美的 随着BDD的发展,越来越多的工具进入了我们的视野。我
80. 们应该认清团队的需求,结合团队的特点选择合适工具,不要 盲目地随大流。下面我来列举一些具有代表性的工具,推荐给 不同类型的团队。 Cucumber 简单来说,Cucumber实际上是一款有一定文档性、可以帮 助团队沟通合作的、提供自动化测试功能的工具。特点是上手 简单、社区活跃、文档表现力不足。所以如果团队刚开始尝试 BDD,更看重自动化测试方面,而对需求文档化要求不高, Cucumber是一个不错的选择。同时Cucumber目前支持Ruby, C#,JVM,JS和C++,众多平台也是一个加分项。 Concordion 与Cucumber相比,Concordion提供了更好的文档支持。 Concordion的Specification是HTML格式的,我们再也不用生搬 硬套的使用Given/When/Then进行功能描述了。在HTML文件 中,我们可以更加自由的描述业务需求,同时可以增加好看的 样式,添加更友好的交互,放入更多的视频和图片等等。 总而言之一句话,HTML比纯文本更加灵活强大,适合阅 读。同时我们也要清楚HTML的学习和维护成本相比纯文本更 加昂贵,非技术的人可能很难单独完成。和技术人员结对完
81. 成,或者在技术人员完成后进行审查也是一个不错的选择。但 由于Concordion目前只对C#和JAVA支持较好,所以如果团队刚 好用到C#和Java,并且非常看重文档化需求,那么Concordion 要比Cucumber更加适合你们。在下面的例子中,我们使用 Concordion生成了“教学评估”相关的需求文档,并且使用了 shower.js增强了用户交互,在保证软件功能的同时,带来了更 好的阅读体验。 交互性更好地需求文档,内容组织合理,阅读体验好。 其中一个需求的详细描述,同时也是自动化测试。
82. Gauge Gauge也在文档方面进行了改善,Gauge的Specification文件 由Markdown组成,相对纯文本有了一定程度的提升,但还是不 如Concordion灵活。Gauge使用Go编写,天然支持并发运行,相 比之下性能要更加有优势。同时Gauge支持多语言实现,目前 支持Java、C#和Ruby,相比Cucumber在跨平台式需要整个切换 工具,Gauge更容易做跨平台。虽然目前Gauge处在开发阶段, 但依然值得关注。
83. 总结一下 1.BDD不是工具,而是一套流程和一系列实践。它需要团 队成员的通力合作,可以帮助整个团队更好的理解业务,理解 软件。 2.Cucumber作为支持BDD的一种工具,不单单是自动化测 试工具。在解决了Cucumber的一些问题后,团队可以更加有效 的使用。 3.Cucumber、Concordion和Guage各有不同,选择一款适合 团队自身需要的工具,也能保证团队顺利运作,少走弯路。
84. 好了少年,我只能帮你到这里了,接下来BDD之路就看你 自己的了。
85. 我在测试移动弱网时踩过的坑 文/安丛 什么是弱网测试 在当今移动互联网盛行的时代,网络的形态除了有线连 接,还有2G/3G/Edge/4G/Wifi等多种手机网络连接方式。不同 的协议、不同的制式、不同的速率,使移动应用运行的场景更 加丰富。 从测试角度来说,需要额外关注的场景就远不止断网、网 络故障等情况了。对于弱网的数据定义,不同的应用所界定的 含义是不一样且不清晰的,不仅要考虑各类型网络最低速率, 还要结合业务场景和应用类型去划分。按照移动的特性来说, 一般应用低于2G速率的都属于弱网,也可以将3G划分为弱网。 除此之外,弱信号的Wifi通常也会被纳入到弱网测试场景中。 为何要进行弱网测试 我当前所在项目的产品是一款适配于低资源环境的医疗IT 系统,目前主要是在坦桑尼亚地区使用。根据资料显示,在坦 桑尼亚等东非国家,普遍使用的都是2G网络,覆盖率达到40% 以上,3G网络的覆盖都非常少,并且稳定性较差。由此,对于
86. 当前的App应用交付要求即至少在弱网以及无网状态下能正常 运行。 如何做弱网测试 弱网环境测试主要依赖于弱网环境的模拟。环境搭建方式 一般有两种:软件方式和硬件方式。软件方式的成本低,主要 就是通过模拟网络参数来配置弱网环境,通常来讲可以达到测 试目的.一般可通过热点共享设置,或者第三方,例 如:Charles,Network link Conditioner.在各类网络软件中,主要 就是对带宽、丢包、延时等进行模拟弱网环境。如果要求更接
87. 近弱网环境,比如现在很多的专项测试,会更倾向于通过硬件 方式来协助测试,但这种方式相对会麻烦很多,一般会由网维 协助搭建,例如树莓派。当然,对于有些无法模拟的情况,只 能靠人工移动到例如电梯、地铁等信号比较弱的地方。 弱网测试时碰到的问题和解决方案 1、现象:用户登录应用时下载初始化数据,下载过程中 因网速太慢点击取消并重新登录,数据初始化完成后出现重 复,造成数据不一致。 原因:数据下载过程中、下载失败后,未进行数据回滚, 中止后重新下载,出现数据重复 解决方案:通过事务处理数据下载逻辑,下载失败后,应 用本地数据库进行数据回滚。 2、现象:用户点击数据上传,数据上传过程中网络弱且 不稳定,基于联网状态自动触发数据上传,导致出现数据重复 写入,形成脏数据 原因:数据上传过程中, 由于失败重传机制,会出现连续 两次写操作,并且未做唯一识别处理 解决方案:根据数据特性,对可能造成脏数据的地方,通 过关键字段,例如创建时间,key-value值等生成hash键,标记 记录唯一性,即数据写入时,检查hash键是否存在,如果已经 存在,当前重复数据丢弃。
88. 3、现象:在弱网环境下,用户输入用户名和密码点击登 录,应用链接超时返回用户名和密码错误提示。 原因:在弱网环境下的连接超时后,按照强网业务逻辑处 理,导致返回超时异常。 解决方案: 弱网连接超时后,检查应用本地数据库是否 有用户登录信息,若存在,获取应用本地用户信息进行登录。 4、现象:在弱网环境下,用户输入用户名和密码后点击 登录,登录过程中应用崩溃并且闪退。 原因:弱网环境下数据下载超时,加载数据严重依赖于后 来的异步加载。数据还没来得及返回,应用跳转到下个 activity,导致崩溃。 解决方案:健壮数据加载流程,通过标记后台数据下载状 态加载界面,依赖数据下载完成后,再进行页面跳转。 5、现象:弱网络环境下,用户请求页面响应时间较长, 等待的过程中,页面上的部分控件仍然可以操作,当用户点击 控件时,出现应用闪退现象; 原因:没有对数据加载流程进行判断,直接暴露控件可 控,当出现依赖数据的控件操作时,没有在数据返回前做兼容 处理。 解决方案:在数据加载过程中,设置页面对外暴露的控件 为“不可操作”,当数据加载完再释放。 6、现象:在弱网环境下,用户第一次输入搜索关键字没 有得到响应后,再次输入全新关键字并发送请求,等待搜索结
89. 果返回后,当前结果页被之前的关键字搜索结果刷新覆盖 原因:中间的请求返回较慢,显示最终的结果后,之前请 求返回的数据应不做处理。 解决方案:对异步请求未完成的任务进行cancel。 总结 当然,出现以上问题的根本因素并不是弱网,在我们平时 的PC应用中一样会遇到,但是这些问题在移动弱网环境下会表 现的更突出。所以综上所述,从功能、性能、稳定、异常处理 等几个维度来归纳场景特性,弱网测试主要集中在如下场景:
90. 容器化时代对测试的机遇 文/梁真 对于工作在复杂系统上的测试工程师,我们眼前浮现的都 是这些人的屏幕上开着N个远程桌面、N个虚拟机,他们在每个 交付迭代周期内都疲于奔命,顾此失彼地应付着各种不同的环 境、浏览器和操作系统。在我曾经工作过的A公司和D公司,测 试和开发人员的比例几乎是1:1甚至更高。 在过去的几年里,测试的工作似乎变得完善和高效,成熟 的敏捷实践使很多测试工作得以自动化,这无疑降低了企业成 本,也使得测试本身变得更有趣,人们有时间去做一些创造性 的工作,而把重复的、了无生趣的工作交给了机器和脚本。 但是,虽然我们做了很多改变,但就目前的情况而言,依 然不是很乐观,我们还是会碰到诸如此类的问题:“我的环境没 发现这个defect,你来帮我重现一下”,当我们信心满满去尝试 重现的时候,却可能再也无法发现这个defect,然后不得不花费 几个人、几个小时、甚至几天的时间去定位和解决它。 再有,很多敏捷团队都会做每日构建,构建成功的前提是 所有的测试都要通过,我们为了减少构建时间、测试反馈时 间,花了大力气去优化和重构,使用了mock技术等等,但对测 试时间的影响依然是杯水车薪。
91. 上述问题仅仅是我们平时工作里遇见的一小部分,对于这 几个问题,我们归结了两点: 1.测试环境不够干净 2.测试执行效率需要大幅提升 我们带着这两个问题,来看近年来火爆的轻量级虚拟化 ——容器技术,它提供了能够独立运行的轻量级虚拟化解决方 案,并且也提供了一种在安全、可重复的环境中自动部署软件 的方式。 传统的硬件化虚拟占用的资源比一个容器要多不止10倍。 我们不敢想象在一个物理机上开上百个虚拟机是什么效果,但 是要实现同样数量的容器是很正常的。容器为我们提供了隔离 的运行空间,每个容器又包含了完整的用户环境。不但如此, 我们还可以通过诸如ansible、puppet、chef这样的自动化运维工 具对不同的容器空间进行批量化操作等等。 从一个测试人员的角度来讲,这恰恰为我们运行测试脚本 提供了丰富的土壤,我们不必担心一些依赖包悄悄地破坏我们 的环境,也不再担心多人在相同的虚拟机或者硬件环境中的操 作污染了环境,使defect无法重现,同时,多操作系统版本、多 尺寸的移动端自动化测试也将从容器化技术中受益更多。 那么另一个问题解决起来也不算难,主流的开源自动化测 试工具Selenium多年前就提供了Selenium Grid,hub/remote的机 制可以很好地帮助我们设计分布式测试环境:
92. 我们可以把这样分布式的环境与自定义的容器化空间结合 在一起,利用提供各种语言支持的并发工具包,让我们在安 全、可重复、可移植的环境基础下,指数级提升测试运行效 率,减少反馈时间:
93. 大部分测试人员对日新月异的技术并不是很敏感,很多时 候,我们可能会认为,这些技术的发展,并不会也并不想知道 这些技术能对日常的测试工作带来多少影响,但其实很多时候 看似孤立的领域,碰撞在一起会有意想不到的火花。 乔布斯曾经说,创新就是把各种事物整合在一起。当你问 有创意的人是如何创新的,他们可能会感到些许愧疚,因为他 们根本没有创造什么。他们只是看到了一些东西。我们对于日 常工作了解得更深更广,我们就会做得越出色。
94. 产品环境下的QA 文/林冰玉 本文首发于InfoQ: http://www.infoq.com/cn/articles/QA-in-Productionpractice 2015年11月ThoughtWorks发布的技术雷达提到一个新的主 题——产品环境下的QA(QA in Production),2016年4月再次 提到。这个主题第一次出现在技术雷达,就深深的吸引了我, 当时我就给测试团队成员转发了这个内容,但同时脑子里也产 生了这样一系列的疑问: • 产品环境下的QA可以做什么呢?有什么挑战,又有哪些 好处? • 它跟类产品环境的QA有何区别,是否就是类产品环境QA 方法的延伸? • 产品环境有运维支持团队(Ops),产品环境下的QA跟 Ops所做的事情又有什么区别与联系? 带着这些疑问,结合项目上的一系列实践,于是有了本 文。 产品环境的特点
95. 为了尽量避免产品环境出现Bug,通常采取的措施是从“类 产品环境”考虑,一步步做好质量控制。其实,如果能从产品环 境做些QA工作,对于产品质量的提高也是有很大帮助的。想要 做产品环境下的QA,首先得了解产品环境有哪些特点: 1.真实、不可破坏 产品环境都是真实用户在使用,是真正支持企业业务运转 的系统,不可以随意在这个环境中做测试,尤其是破坏性的测 试。 2.基础设施差异 产品环境往往有着比类产品环境更复杂和健全的基础设 施,可能会出现类产品环境不能预测到的缺陷和异常。 3.系统复杂度 产品环境需要与多个不同的系统集成,系统复杂度会比类 产品环境高很多,这种复杂的系统集成很有可能导致一些意外 的情况出现。 4.数据复杂度
96. 产品环境的数据量和数据复杂度也是类产品环境无法比拟 的,通常都不是一个数量级的数据,容易引发性能问题、或者 一些复杂的数据组合导致的问题。 5.用户行为千奇百怪 产品环境中用户分布广泛,使用习惯各种各样,导致用户 行为千奇百怪,某些使用行为可能就会产生意想不到的问题。 6.访问受限 产品环境由于是真实业务线上的系统,对安全性和稳定性 要求更高,服务器通常不是所有QA可以随便访问的,这种访问 受限的情况对于产品环境的一些缺陷排查带来了很大的不便。 7.真实的用户反馈 用户在产品环境中使用,能够提出一些真实而重要的反 馈,但是开发团队往往不能直接接触终端用户,QA也就没有办 法获得第一手的用户反馈,这些反馈常常需要通过支持团队来 转述。
97. 产品环境的这些特点决定了QA在产品环境不是想做什么就 能做什么的。原来类产品环境那套质量保证理论和方法都行不 通了。那么,产品环境下的QA又有哪些特点呢? 产品环境下的QA的特点 一、不同于类产品环境的QA 产品环境的特点决定了产品环境下的QA是跟类产品环境的 QA不同的,前者不能主动地去测试产品环境的系统,但是可以 做到下面这些:
98. 产品环境下的QA 1.引入产品系统的监控,制定监控预警标准,找出产品环 境下使用的质量度量。比如,分析产品环境日志,收集系统运 行的错误、异常和失败等信息;或者利用网站分析工具收集用 户使用应用程序的数据,分析数据量需求、产品的性能趋势、 用户的地域特征、用户的行为习惯和产品在同类型产品市场的 占有率等。 2.收集产品环境下最终用户的反馈,对反馈进行分类分 析。用户反馈通常有缺陷、抱怨和建议,针对不同类型需要采 取不同的处理方式,利用用户反馈,改进系统功能,提高产品 质量,同时优化业务价值,扩大产品的市场影响力,提高企业 竞争力。 因此,产品环境下的QA并不是类产品环境QA活动的简单 后延,它有着自己独特的特点。
99. 二、不能独立存在 产品环境下的QA所设置的监控标准是根据系统的行为特点 和在类产品环境下的表现来定义的,产品环境下各项反馈的分 析结果反过来又影响着类产品环境的QA过程,而且这两者是相 辅相成的,只有形成了良性环路,才能把产品环境下的QA做 好。 三、有别于Ops 产品环境设置监控预警和收集用户反馈不都是Ops团队可 以做的事情吗?还要QA参与干什么?是因为QA有着独特的思
100. 维模式和视角,QA的参与能够帮助更好的分析产品环境下收集 到的各种反馈,并且基于对于系统的了解,将这些反馈更好的 应用到日常的开发工作中。QA在整个监控预警、收集和分析用 户反馈的过程中主要充当分析者和协调者的角色,对产品环境 下的质量保证工作起到至关重要的作用。 这时候的QA带着QA和Ops的帽子,兼具QA和Ops的部分职 责,类似于QAOps,不过现在都提倡不要有独立的DevOps,我 们也不要独立的QAOps角色,只是让QA这个角色可做的事情得 到了延伸和扩展而已,本质上还是QA。 四、跟APM的侧重点不同
101. 可能有人会觉得产品环境下的QA跟APM有相似之处,那 么这两者是不是一回事呢? 维基百科这样解释APM: “In the fields of information technology and systems management,application performance management (APM) is the monitoring and management of performance and availability of software applications.(在信息科技和系统管理领域,APM对软 件应用程序的性能和可用性的监控和管理。)” APM更多的是从性能角度出发去管理和优化应用,可以发 生在各个阶段,不一定是产品环境。产品环境下的QA是指在产 品环境进行一系列的监控和数据收集,从系统功能、性能、易 用性等多个方面进行优化,从而最终优化业务价值。因此,两 者是不同的。 产品环境下的QA在项目上的实践 我所在的项目是一个离岸交付项目,采用敏捷开发模式, 四周一次发布到产品环境,开发的系统包括一个内部员工使用 系统和一个外部用户使用的网站,用户遍及全球,整个项目已 经持续了七年有余。产品环境具备前面所描述的所有特点,并 且产品环境每日的错误日志达到几千条。正是由于错误日志的 数量到了一个不能忍的程度,产品环境才引起了各方的关注, 也使得产品环境下的QA迎来了试点的最佳时机。产品环境下的
102. QA在我们项目上的实践主要是三部分内容:日志分析和优化、 Google Analytics数据分析、用户反馈的收集和分析。下面逐个 介绍。 一、日志分析和优化 既然错误日志那么多,首先就是从这些错误日志下手。项 目使用的日志分析工具是Splunk,这个工具功能强大、使用方 便,关于工具的详细信息可以参考官网。下图所示为使用 Splunk通过指定条件搜索日志文件得到的结果页面,结果集里 四条类似乱码的东西就是代表有四种类型的错误日志,每种错 误出现的数量和百分比都有统计,点击每条结果可以查看详细 的错误日志信息。
103. 关于日志的分析和优化,我们在项目上做了如下工作: 1.分析产品环境的错误日志 专人负责产品环境错误日志的分析,挑出优先级高的进行 修复处理;对新功能进行日志监控,确保上线后能够运行正 常。 2.监控测试环境的错误日志 把产品环境错误日志的分析方法应用于测试环境,让bug发 现提前到测试阶段。据不完全统计,最近两三个月通过这种方 式发现并修复了好几个潜在的Bug。
104. 3.利用日志监控不同功能的性能 Splunk里设有专门的统计和监控系统性能的Dashboard,QA 会定期从里边拿出高优先级的给开发人员进行性能调优。 4.日志记录标准化 现有的产品环境日志记录中存在一些问题,给分析工作带 来不便。团队为此进行讨论并达成共识: • 将日志输出到各个服务器的同一个路径; • 统一日志记录格式,并且尽量记录更全面的信息以便进 行后期的日志分析; • 清晰定义各个日志级别(Debug,Info,Warning, Error,Critical,Fatal),将已有的误记成错误的日志降低 到正确的级别,对于新功能则严格按照所定义级别记录日志; • QA在用户故事(Story)的开发机验收(Dev-box Testing or Desk Check)阶段负责跟开发人员确认相关日志 记录是否符合标准,并且通过测试环境的日志监控可以及时验 证新功能的日志记录情况。 二、Google Analytics数据分析 Google Analytics(以下简称GA)是项目用来统计网站使用 情况的工具,从GA上可以获取很多有价值的信息,对这些信息 进行分析是我们实践的产品环境下QA的另一块内容,具体做了
105. 下面几项工作: 1.操作系统和浏览器使用情况分析 根据产品环境操作系统和浏览器使用比例去调整测试环境 所使用的系统,比如从重点关注IE9调整到IE11。 2.分析QA测试跟用户真实行为的差异,及时调整测试 根据GA上用户访问的路径可以发现我们QA的测试跟一些 真实用户使用习惯的差异,这样如果按照我们通常的路径去测 试,可能有些问题难以在测试阶段被发现。比如,QA在测试环 境通常打开“工作记录”的方式是这样的: 而我们从GA上发现真实用户使用过程中,打开“工作记 录”最多的路径是这样的: 发现了这种差异,QA就要在测试时候做相应的调整,让测
106. 试更接近用户的行为习惯。 3.提炼关键业务场景,增加测试覆盖 利用GA的数据结合客户业务人员对系统各功能使用情况的 介绍,我们提炼出系统最为关键的业务场景,并且尽量分层 (参考测试金字塔)实现自动化测试覆盖,以减轻QA回归测试 的压力。 4.发现用户较少使用的功能,优化业务流程 类似的,我们还可以通过GA发现一些用户较少使用的功 能,QA的测试基本不需要太多去关注这些功能,同时可以跟业 务分析人员一起分析功能不被使用的原因,在后续的功能开发 过程中可以作为借鉴,从而优化业务流程。 5.分析用户地区分布和使用时间段分布,合理安排定时 任务运行时间 通过GA上的数据,统计出哪个时间段是相对空闲的,在不 影响真实业务的前提下,把一些资源消耗较大的任务安排在那 个时候执行,合理分配资源以减轻服务器的负担,尽量减少对 用户的影响。 6.监控系统性能变化趋势,规避性能风险 QA定期查看网站平均访问时间,监控性能趋势,同时要重 点关注那些访问非常慢的页面或功能,必要的时候创建性能缺
107. 陷卡,由开发人员来调查分析并修复或优化。 7.确保GA能够统计到所有需要统计的功能 GA数据虽然很有用,但前提是正确记录了所需要统计的数 据,所以在开发过程中要确保GA嵌入到了各个需要统计的功能 或页面,QA在类产品环境测试的时候需要验证这一点。 下图为从GA拿到的浏览器分布情况和页面平均加载时间的 一些数据: 三、用户反馈的收集和分析 作为开发团队的我们基本是不能直接接触到系统终端用户
108. 的,直接接受反馈的是客户的Ops团队,QA主要通过下面几个 途径去协助分析和梳理用户反馈: 1.跟Ops和业务的定期沟通会议 QA会定期跟客户的Ops和业务人员沟通,了解用户对于现 有系统的反馈,找出在测试中需要重视的功能特性,对类产品 环境的测试关注点做出相应的调整。 2.培训Ops人员 指导和协助客户Ops人员利用鱼骨图(Fishbone Diagram) 的方法对收集到的用户反馈进行分析和分类,将分析结果跟现 有的测试覆盖情况进行对比,找出测试过程的薄弱环节,并做 出改进。比如,如果某个浏览器出现的bug比较多,我们的测试 就要加强该浏览器的关注;或者在发现不同用户权限导致的问 题出现频率高,那就得在测试中注意覆盖不同用户角色的测 试,反之则减弱不同用户的覆盖,主要测最常用的那类角色即 可。 3.调查和跟踪产品环境Bug 帮助重现和调查用户反馈过来的产品环境Bug,并负责跟 踪修复和验证;对于难以重现的问题,则添加日志监控,通过 分析收集到的日志信息找出问题根源,从而进行修复。 4.协助梳理业务需求
109. 系统要增加某个新功能的时候,客户Product Owner(以下 简称PO)或其他业务人员跟用户会一起沟通该功能相关业务现 有的使用习惯、使用场景,QA也会尽量参与这种会议,收集用 户第一手需求信息,这些信息对于后期该业务功能开发时候的 QA过程将非常有帮助。而还有些功能,PO可能一时也拿不定 主意要做成什么样子,我们会发布MVP的版本给用户使用,QA 协助业务人员分析用户使用后的反馈,梳理更具体的用户需 求。 总结 1.产品环境下的QA将工作范围从需求扩大到了产品环境, 增加了更多的反馈来源,跟持续交付结合,可以帮助持续提高 产品质量、优化业务价值。 2.产品环境下的QA给的工具箱添加了更多的工具,提供了 更多评估和提高系统质量的选项,是QA们值得深入研究的话 题。 3.产品环境下的QA不能走得太远,必须先做好类产品环境 的质量保证,并且仅适用于持续交付实践的比较好的组织。如 果连类产品环境的质量保证都做不好,就想着去做产品环境下 的QA,那只能是舍本逐末、事倍功半。
110. 致测试同仁们:让我们一起做安全测 试吧! 文/覃其慧 本文首发于InfoQ: http://www.infoq.com/cn/articles/to-test-colleagueslet-us-do-a-safety-test 今天,很多的软件并没有经过专门的安全测试就被放到互 联网上,它们携带着各类安全漏洞暴露在公众面前,其中一些 漏洞甚至直指软件所承载的核心敏感信息或业务逻辑。这些漏 洞一旦被不怀好意者利用,很可能会给企业造成经济损失。带 来负面声誉影响的同时,还可能被起诉、遭到罚款等等,细思 极恐。其中的一部分原因是企业本身安全意识不强,但是很多 时候虽然软件企业已经开始意识到这些问题,却苦于缺少专业 的安全测试人员,他们不得不冒着极大的风险先上线赌一把运 气再说。 既然如此,作为质量代言人的我们,怎能对此置之不理 呢? 你也许会问?怎么理?安全测试水太深了。 安全测试并不遥远
111. 是的,安全测试在软件测试里面是一个很特别的科目(或 作“工种”),很多人都觉得这个科目应该全权交给神秘的安全 测试人员来管。这个观念导致很多测试人员徘徊在安全测试的 门口却迟迟不进去,包括我自己。 直到后来,我非常有幸能够在不同规模的软件开发项目上 跟“神秘的安全测试人员”学习如何进行安全测试,发现“神秘的 安全测试人员”不光是名字跟我们一样都有“测试”二字,所做的 事情在本质上也跟我们测试人员有很多相通之处。 想想看我们都做过什么: 我们修改过url的参数,对不对?他们也是! 我们在数据输入处提供过不合法的数据,对不对?他们也 是! 我们尝试过修改只读数据,对不对?他们也是! 我们也测过用户会话是否如期timeout,对不对?他们也 是! Ok,这还不是全部。他们也做测试计划、测试用例设计、 bug分析与管理等等。所以,安全测试离我们并没有那么遥远。 当然,我必须承认,安全测试是非常复杂的。一个专业的 安全测试专家在某种程度上来说是一个全栈工程师。所以,想 要在安全测试上一夜成才不太容易。不过好消息是,作为测试 人员的我们却有得天独厚的优势,使我们能够在安全测试上快 速起步,帮助团队尽快展开预防并检测安全漏洞的工作。 在这 里我想要跟大家分享一下在敏捷开发团队中如何利用我们的测
112. 试经验开展安全测试。 安全测试并不陌生 首先,让我们先来了解什么是安全测试,我们作为测试人 员有什么可以直接用上的技能和经验。 简单来说,安全测试其实就是一个发现软件安全漏洞的过 程,旨在保护软件系统的数据与功能。它跟常规测试相似的地 方至少有以下几点: NO. Summary Details 预防、检测系统的缺陷 1. 目标类似 (尽早、频繁反馈系统 质量信息) -了解系统业务需求 -针对业务与系统功能 设计用例 -与其他角色一起启动 2. 在软件生命周期中的工作过 程类似(以敏捷团队为例) 需求的开发 -与其他角色一起在开 发环境验收需求 -在测试环境进行全面 测试 -分析并总结测试结果
113. -反馈测试结果 面向用户的测试场景非 3. 测试用例有很多重合 4. 都需要有探索的过程 5. 常类似 对会对不同的业务场景 有目的的进行探索 都要有测试人员必备的“怀 对开发人员的代码保持 疑态度” 友好而警惕的态度 1.目标类似 不管是常规测试还是安全测试,都有一个原则:预防胜于 检测。这个比较容易理解,不管是常规测试的缺陷也好,还是 安全测试的漏洞也好,如果能预防使它不发生,就省了后期的 修复与验证工作。如果不能成功的预防缺陷,能早一些发现的 话,肯定比晚发现的修复的成本低。 2.在软件生命周期中的过程类似 以敏捷开发团队为例,常规测试人员在各个阶段做的事 情,安全测试人员也要做: • 了解业务的需求,以避免混乱的测试优先级; • 针对业务与系统功能设计用例:常规测试需要关注系统 功能,安全测试同样也不能脱离系统功能;
114. • 与其他角色一起启动需求的开发:沟通测试用例,避免 因为沟通不足造成返工; • 与其他角色一起在开发环境验收需求:尽早提供反馈, 发现缺陷时开发可以马上修正; • 在测试环境进行全面测试:针对端到端的场景进行测 试,尽可能把第三方系统(如果有的话)也包括进来; • 分析并总结测试结果:整理问题清单,排列优先级; • 反馈测试结果:把测试结果反馈给团队等干系人。
115. 3.测试用例很多重合 在面向终端用户的测试场景上,常规测试的用例与安全测 试的用例是非常类似的。比如对于登录系统的功能,不管是常 规测试还是安全测试,我们都会测试用户输入正确的用户名是 否可以登录,输入错误的用户名或密码系统会如何反应。 比如我曾经工作的一个搜集报税人信息的系统,不管是常 规测试还是安全测试,都会测试系统的登录,系统信息的录入 与编辑,文件的上传等等。因为在每一个终端用户可以操作的 场景上,都可能会有安全漏洞存在。所以,有了常规测试的经 验,我们就相当于有了不少安全测试用例的储备。 4.都需要有探索的过程 测试是一个了解软件系统能否完成我们预期的过程,也是 探索系统还有哪些我们没有预期的行为的过程。安全测试的过 程需要把探索的目标转向安全漏洞。当我们这么做时,我们同 样会得到很多探索的乐趣。 5.都要有测试人员必备的“怀疑态度” 相信咱们测试人员都非常熟悉一个场景--开发人员 说:“我只做了一个很小的代码改动。”然后我们带着友好而警 惕的态度,发现这个“很小的改动”引发了很大的问题。不管是
116. 在安全测试还是非安全测试,这个警惕性是我们都需要保持的 良好传统。 那么,有了这么多类似的地方,还缺什么呢?如果想要做 专家,还差很多。但是如果想马上安全测试上起步,我们可以 先做下面的改变。 安全测试从何做起 第一,转换视角 在我看来,不管是带着全栈的经验,还是只有部分技术知 识,想要做好安全测试必须先转换我们观察软件的视角。举个 例子,让我们看看下这幅画: 同样一幅画,有人一眼看过去看到的是两个人脸,而有人 看到的是一个花瓶。这就是观察视角的不同造成的。 在我刚开始接触安全测试时就很深地体会到了这一点。当 时我在测试一个Web应用的用户登录功能。当我输入错误的用 户名来试着登陆时,浏览器上的提示信息为“该用户名不存 在”。当我尝试正确的用户名而错误的密码时,提示信息变 成“密码输入错误”。对于这个清晰的错误提示我非常满意。试 想我若是一个真实的终端用户,这个信息有效的帮助我缩小纠 错范围,提高效率,非常好。 可是,就在我身边坐着的安全测试人员马上跳了出来:“这 个提示信息需要改!敏感信息暴露了!”看到我一脸茫然,这位
117. 安全测试人员告诉我,通过我们的提示信息,恶意的系统使用 者可以推测出哪些用户名已经存在于系统中,然后利用这些用 户名可以再进行密码的暴力破解,缩小破解的范围。所以,这 个信息虽然为合法用户提供了便利,也为不怀好意的系统使用 者提供了便利。而往往这种便利为恶意的系统使用者带来的好 处远大于给合法用户带来的好处。 这个经历在让我受震动的同时,也使我意识到可能很多安 全漏洞之前就摆在我的面前了,我却没有看出来,因为我把它 们过滤了。事实证明,在后来经历的不同项目中,当我转换了 视角,有些安全漏洞不需要我去找,而是自己跑到我眼前来 的。真是得来全不费功夫。 第二,改变测试中模拟的对象 为了能从不同的视角来观察软件,我们必须改变我们所模 拟的对象。这也是一个让我们刻意练习转换视角的有效方法。 我们在做非安全测试的时候通常把自己想象成一个合法用 户,然后开始验证系统是否能完成预设的目标。比如对于一个 网上商城,我们会验证系统是否能让用户完成商品的浏览与购 买,我们也会测试一些异常的行为,比如购买的商品数量不是 数字而是一串无意义的字母时,看系统是否能比较优雅的做出 回应。我们这么测试的目的往往是为了确保用户误操作以后还 能够继续他们的购买,或者说不要给系统造成什么严重的伤
118. 害。 如果要做安全测试,我们则必须去模拟系统的另一类使用 者-恶意用户。他们的目的是寻找系统中可钻的漏洞。比如同 样是一个网上商城,恶意用户的目标之一就是要想办法以较少 的钱,甚至不付钱就能拿到商品。所以,如果恶意用户进行 了“误操作”,他们不会停留在“误操作”,而是通过“误操作”来 看系统是否给自己提供更多的线索。 所以,我们需要转换测试时所模拟的对象,把思维从一个 合法用户的视角中拉出来,转换成一个恶意用户。这需要一点 时间,就如同之前看到的画,如果我们一开始看到的是人脸, 要想下一次第一眼看到的是花瓶,我们需要时间来刻意练习。 第三,使用专用的测试工具 有了思维的转换,我们可以加入新的测试想法。但是,在 具体做安全测试的时 候我们会发现并不是那么容易去模拟恶意用户的行为。毕
119. 竟系统的前端会给我们设置很多的屏障。而且恶意用户可不总 是从系统前门进去的。这时候,使用一些工具,比如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个全新的事情。只是在每个需要测试 人员出现的地方增加了安全的工作而已。
120. 1.识别系统中有价值的数据 很多人认为执行测试才是测试,而我们的安全测试从这里 就开始了。 了解业务之后,我们需要考虑系统中会有什么有价 值的数据。这是为下一步加入恶意用户需求做准备。对于一个 网上商城,有价值的数据可能包括产品信息、订单信息、用户 信息、支付,等等。 这个环节对我们测试人员来说并没有太多 额外的工作,毕竟我们做非安全测试的时候也需要了解业务。 不过要注意了,我们要测试的“图片上传功能”是一个涉及有价 值数据的功能。我们需要提高警惕了。 2.在需求阶段加入恶意用户需求 恶意用户需求是用来记录恶意用户想要在系统中达到的目 的。与普通用户需求的区别是,我们不是要去实现它,而是使 用它来帮助我们远离对系统使用者“不恰当的信任”。通常我们 需要针对每一个合法用户需求来增加一个或多个相对应的恶意 用户需求。
121. 举个例子,如果我们这个“图片上传功能”的合法用户需求 为:作为一个买家,我想在对商品进行评价的时候上传图片作 为买家秀,以便于参加返现营销活动。那么对应的恶意用户需 求可以是:为一个恶意用户,我想破坏买家秀返现活动,以便 破坏商城的营销活动。“破坏买家秀返现活动”是一个大的目 标。为了设计用例方便,它可以被细分为一系列小目标。比如 让用户无法上传图片、让页面无法正确显示图片等等。 有了恶意用户需求的主干信息,我们就可以开始下一步设 计安全测试用例了。 3.针对“恶意用户需求”设计测试用例 现在我们需要做的是努力把自己限制在“恶意用户”的角度 做头脑风暴:“到底有什么方法可以使买家无法上传图片信息 呢?”,“让页面无法正确显示买家秀图片又怎么做到?”嗯,也 许最直接的办法就是让服务器所在的机房断电、断网之类的。 这是些不错的想法,虽然执行难度有点大。没关系,记录下 来。除此之外,我们还可以有其他测试用例,比如: • 使存储图片的磁盘空间被占满而无法接受新的图片; • 使处理上传图片的进程繁忙而无法接受新的上传任务; • 上传特别大的图片使用户的客户端需要很长时间才能下 • 上传伪装成图片的恶意代码,进一步获取服务器权限, 载完 删除所有的买家秀图片;
122. • 等等 如果这个时候想到新的测试用例也同样记录下来,比如“我 想不购买也上传买家秀图片以获得返现”之类的。 不用太担心这个阶段的测试用例过于“疯狂”或者不够完 整,毕竟我们对于系统的实现还不是很了解。我们会在接下来 的环节中完善具体的步骤。 4.参与启动恶意需求的开发(evil story kickoff) 在开发人员开始开发合法用户需求之前,我们需要跟业务 分析人员、开发人员一起沟通需求的内容。在敏捷软件开发项 目中我们叫它story kickoff,即用户故事启动。当有了对应的恶 意用户需求时,我们必然也要把它也加到启动的范围里。目的 是把我们头脑风暴出来的测试用例跟所有的角色来沟通。预防 胜于检测。 5.在开发环境验收恶意需求的实现 100%预防软件的缺陷与漏洞是不太可能的,所以这个环节 的存在是为了提早反馈。 我曾经经历过一个项目,都快上线了才决定做安全测试, 结果测出来的问题之一是用户会话(user session)不能正确过 期的问题,经过一番研究,发现需要对系统设计的架构进行比 较大的修改,只能做个临时的修复让系统先上线,然后再把系 统的架构给改了,重写这部分功能,重新测试。代价非常高。
123. 所以不管是安全测试还是非安全测试,”在开发环境验收恶意需 求的实现“这个步骤都不能缺少。 而这个环节存在的第二个目的是让我们可以从开发人员那 里得到支持-具体实施的细节,帮助我们完善具体的测试用 例。比如在这个时间点我们若从开发人员那里得知系统的后台 没有对图片上传者做身份验证,我们就可以至少增加一个测试 的用例:“恶意用户以其他用户的身份上传一个风马牛不相及的 图片”。有时候错误的图片比没有图片更具有杀伤力。 6.在测试环境中进行安全测试 终于到了运行测试的阶段。可能这个时候我们之前想到的 测试用例已经被开发人员给解决了。如果是这样那就太好了。 但是,事实并非有这么美好。第一,可能这些用例只是在开发 环境上成功通过了,但是在理想的测试环境里,也就是类产品 环境里,这些用例可能并不能完全通过;第二,肯定还有其他 需要探索的地方。这时我们就可以用OWASP Zap、Burp这样的 工具来辅助我们把之前的安全测试用例执行一次,同时还再可 以对系统的安全性做一下探索测试。 7.向团队反馈所发现的安全漏洞 都测得差不多的时候,我们就可以向团队以及相关干系人 汇报安全测试的结果了。跟非安全测试不同的地方是,当我们 反馈安全漏洞的时候,要考虑不同漏洞结合起来是否会增加系
124. 统的安全风险。举个例子:如果有两个安全漏洞,一个是系统 没有很强的用户账户密码规规则,另一个是系统没有对上传图 片的大小做限制,那么恶意用户把这两个漏洞一结合起来,事 情就比原来风险大很多。那么我们就必须建议提高这两个漏洞 中任意一个的优先级。 当我们用“三板斧”走完这七步以后,我们已经可以把很多 安全漏洞都挖出来了。是不是没有想象中的难?所以,测试同 仁们,让我们做安全测试吧!