都是脏数据惹的祸

“小光,今天那个诡异的生产环境问题找到原因了吗?”
“还是数据问题!之前做的一个功能有一部分数据迁移工作没有做好,导致生产环境有脏数据,委托人的联系人已经不为该委托人服务了,应该移除掉的…=-#~)@/-$*…”
“又是脏数据…@=@”
“嗯,好在不是代码问题。”

这是在蓝鲸项目发生的真实对话。其中提到的脏数据(Dirty data),也叫坏数据(Bad data),通常是指跟期待的数据不一样、会影响系统正常行为的数据。

蓝鲸项目的QA会定期分析生产环境的缺陷,当定位某个缺陷为脏数据引起之后,往往就到此为止了。生产环境下的缺陷分析流程是这样的:

生产环境缺陷分析流程

调查分析生产环境缺陷,到最后定位是数据问题的时候,总是让人浑身轻松… 于是,“脏数据”就跟测试的“随机挂”一样,成为了光荣的“背锅侠”!

脏数据 ≠ 代码问题,真的是这样吗?先来深入了解一下脏数据。

脏数据是怎么回事?

脏数据产生的原因多种多样,有的甚至很难解释清楚到底发生了什么…

通常,以下原因可能造成脏数据:

  1. 脏读:读了事务处理中间状态的数据
  2. 重复插入了相同的数据:多次点击同一个按钮导致
  3. 不能为空的字段存为空:数据库字段没有验证,或者对于历史数据没有做好迁移处理
  4. 人工录入不合法的数据:比如电话号码含有特殊字符
  5. 运行SQL脚本插入了不合法数据:比如不同实体id搞混等
  6. 存入了多余的空格
  7. 测试环境可能由于部署了半成品产生一些不合法数据
  8. ……

因此,脏数据跟代码有关,脏数据的产生是因为没有做好防御工作!

脏数据有哪些危害?

根据不同的系统、不同的业务,脏数据带来的危害也会不一样。

  • 脏读产生的数据往往是错误的,导致数据不真实性,或者数据的不一致性;
  • 重复和其他不合法数据则可能导致系统行为的不正常,有时候还可能导致非常严重的故障,甚至有些没有暴露的脏数据可能带来不可预知的致命错误,危害可能是相当大的。

脏数据带来的危害很难估量,有很大的不可预测性,对于脏数据的预防至关重要。

那么,如何能够防范于未然呢?

如何预防脏数据的产生?

优化的缺陷分析流程

尝试对脏数据引起的生产环境缺陷做进一步分析,总结出脏数据的几种类型,可以在敏捷软件开发生命周期的不同阶段对其进行防御。

业务需求分析阶段

在业务分析的时候,根据业务需求,明确业务相关数据的特定要求:

  1. 不能为空的字段
  2. 不能重复的数据
  3. 日期范围
  4. 电话号码可以有“ext.”、“+”和“-” 但不能有其他字符
  5. 特殊字符的限定
  6. 功能升级的时候考虑已有数据的迁移
  7. 还有一些跟常识不同有特定业务含义的数据需求
  8. ……
数据库和代码实现阶段

明确了数据的需求,可以根据需求定义和软件使用常识,在实现层面对数据进行严格的约束和校验:

  1. 数据库表的主外键、字段类型、是否允许为空,事务处理隔离等
  2. 前后端对数据进行严格的校验,防止各种手段存入不合法的数据,包括需求定义的数据和常识性的数据,比如身份证号码最多18位等
  3. 考虑多用户同时处理可能带来的并发问题
  4. 防止按钮或者链接被重复多次点击,可重复点击通常在网速较慢时可能存入重复数据
  5. 程序读取数据的时候进行处理,比如去掉多余空格、去重、大小写不敏感数据的处理
  6. ……
测试的进一步保障

有了需求定义和实现层面的校验,大部分的不合法数据被阻止了,但是还是会有漏网之鱼,在测试的时候继续采取相应的措施来进一步防御。

  1. 业务需求规定的数据:这个毫无疑问是需要测试的,有底层的单元测试覆盖会更好
  2. 常识性的数据:由于不同的人可能有不同的常识,这些问题在测试的时候还需要特别关注
  3. 探索隐藏边界:关于隐藏边界的概念大家可能不是很熟悉。咱们通常说的等价类、边界值分析方法设计测试用例,都是根据可见的边界来考虑的,其实咱们程序后台可能还存在一些隐藏的边界,也是很有可能会导致数据问题的,需要在测试过程中进行探索发现它们并进行验证。

关于隐藏边界,可以参考John Ruberto的文章《Uncovering Hidden Boundary Values in Testing》,里边提到了四种隐藏边界:数据类型边界、信任域边界、特殊数据值、复活节彩蛋。除此之外,咱们平常测试过程中可以多积累,总结出还有哪些可能会导致数据问题的隐藏边界。

对线上用户的培训

做了前面一层层的防御,如果最终用户在使用的时候能够按照规范操作数据,对减少脏数据的产生会很有帮助。

下面两个措施可以培训用户更规范的操作数据:

  1. 在界面上给出清晰的提示,告诉用户某些数据输入的要求
  2. 给用户培训或者提供用户手册,告诉用户该怎么正确使用系统

如何处理已产生的脏数据?

脏数据的处理

有那么多预防脏数据产生的方法,但相信脏数据的产生还是在所难免的。脏数据一旦产生,导致的系统行为也是不可预测的,可能无足轻重,也可能暴露非常严重的缺陷。该如何应对产生的脏数据呢?

脏数据产生以后有两种存在形式,一种是已经引起某些问题被发现了,另一种是还不被人知道,不知道哪天会发生什么样的问题。

  • 已经暴露的脏数据

对于已经暴露的脏数据,首要的是对数据的快速修复,让系统恢复正常运转。对于专业的脏数据处理可以了解一下数据清洗(Data cleaning)技术。咱们平常对于脏数据的修复,可以根据业务需求,采用数据库脚本修复,或者在前端执行JS脚本来修复。

修复数据需要特别注意不要引入新的脏数据,编写脚本之前要理清相关业务和数据之间的关系,编写好脚本之后要经过严格的测试才能在线上环境执行。

修复数据的同时,需要进一步调查数据产生的原因,检查可以在哪个环节加固防御措施,以尽量减少类似数据问题再次发生的可能性。

  • 未暴露的脏数据

这样的数据,其实我们并不知道它的存在,就像一个在黑暗处的幽灵,不知道什么时候会给系统带来麻烦。

由于系统环境的复杂性、用户行为的多样性,生产环境更加容易产生脏数据。尽早发现这种潜在危害的脏数据非常重要。

蓝鲸项目就是这样。在跟客户做支持的同事沟通过程中,最大的担忧就是生产环境的数据总能发现问题,如何能够让这些问题尽早暴露出来?

推荐生产环境下的测试(Testing in production,TiP)的一些实践。

1. 直接在生产环境测试

生产环境是高度受保护的,不可以随意测试,以免破坏生产环境的稳定性。在生产环境写入数据要特别谨慎,大批量的读操作也要注意对系统性能的影响。

有些可以隔离出来的功能或操作,相对来说是安全的,可以在生产环境直接测试。比如,蓝鲸项目的邮件服务,常会在生产环境部署单独的服务器来测试。

需要根据项目真实情况去做决定。

2. 将生产环境数据清理后用于测试环境

生产环境数据含有PII(个人身份信息,需要保护的隐私信息)或者其他机密,通常不能直接用于测试环境。

将生产环境数据的PII和其他机密信息清除后用于测试环境,测试人员基于这些数据做测试,就能有效的提前去发现由于生产环境数据引起的问题。

这个方案很好,但是要权衡ROI。对于一些复杂的系统,数据库结构过于复杂,清理的成本太高,也是不太现实的。

3. 利用蓝绿部署等TiP实践

蓝绿部署是一种通过运行两个相同的生产环境“蓝环境”和“绿环境”来减少停机时间和风险的技术,是TiP非常典型的一个实践。

在任何时候,只有一个环境是活的,活的环境为所有生产流量提供服务。通常绿环境是闲置的,蓝环境是活的。部署新的版本到绿环境,可以先进行测试,而不会给真正在使用的蓝环境带来影响。完成部署和测试以后,再进行蓝绿环境的切换。

此技术可以消除由于应用程序部署导致的停机时间。此外,蓝绿部署可降低风险:如果新版本在绿环境上发生意外情况,可以通过切换回蓝环境立即回滚到上一版本。这样就有机会提前发现脏数据可能引起的问题。

类似的技术,还有金丝雀发布等,也有助于提前发现脏数据的问题。

写在最后

脏数据的防御是关键

这跟敏捷测试的质量内建原则是一致的。质量内建强调缺陷预防,在预防缺陷产生的同时,要加强对于脏数据的防御。根据敏捷测试的节奏,在敏捷开发生命周期各个环节做好脏数据的预防和处理工作,尽量减少脏数据给生产环境带来的危害。

脏数据的防御是关键

如果由于各种原因防御工作不到位,脏数据产生后也要分析总结,回过头来指导开发环节的工作,进一步加强防御。

脏数据让我们又爱又恨

恨的是脏数据的产生总是会导致系统行为的不可预测,让系统质量保障变得复杂。
尤其是一些脏数据不停的出现,还总是找不到原因的时候,很让人抓狂!总想到此为止,让脏数据来背锅。

但这不是明智的做法,脏数据都是有原因的,不挖掘出真正的原因,可能带来更加意想不到的后果。找出根因,做到防微杜渐,才是正道。

爱的不是因为脏数据可以帮我们背锅,而是它的存在可以帮助我们暴露程序潜在的问题,是做好系统质量保障工作、生产环境下的QA不可或缺的助手。

QA朋友们,请加强对脏数据的重视,善待脏数据!

数字化时代的软件测试

数字经济高速推动着一个无情的市场,所有利益相关者通过设备和应用网络进行交互,一个微观时刻足以让市场领导者摆脱优雅。 这种对速度的痴迷能否淡化质量定性方法?这份《World Quality Report 2017-2018》带你来一探究竟。

现代QA和测试部门重点关注的领域

敏捷和DevOps已经成为数字化转型的重要工具,同时,质量保障和测试工作也随之发生变化:

  • 中央治理和控制减少,团队选择方法和技术的自由度增大;
  • 部署速度提高和应用程序日益复杂化,软件错误和故障的风险增加;
  • 软件质量对品牌的影响巨大,但这已经不是最高优先级的目标,日趋成熟的尽早质量保障实践可以帮助纠正品牌和形象方面的缺陷;
  • 最终用户的满意度和安全性是最重要的两个方面,要确保应用程序的功能和非功能质量,同时需要找到成本和风险的平衡点。

调查结果表明,现代QA和测试部门需要重点关注的领域是以下三个方面:

1. 智能测试自动化和智能分析

智能测试自动化和智能分析将成为支持测试的关键,因为它们可以实现智能决策,快速验证和自动调整测试套件。测试自动化的范围从简单地将测试活动(计划、设计和执行)自动化发展到自动化测试环境和测试数据配置。

然而,调查结果显示目前自动化还处于不足的状态,尽管从自动化中获益的组织数量在增加,但产生的价值没有根本变化,测试自动化水平仍然很低(低于20%)。

速度将推动更智能的自动化需求,需要找到提高自动化水平的方法。

2. 智能测试平台

智能测试平台需要应对测试环境、数据和虚拟化日益增长的挑战。真正的智能测试平台的远景超越了生命周期自动化,需要实现自动配置的完全自我感知和自适应环境,以及支持自动化测试数据生成和测试数据管理。

测试环境、测试数据和虚拟化是三大挑战,同时也为自动化提供了巨大的机会。结合智能生命周期的自动化,将使QA和测试进入下一个演进阶段,称之为智能QA,这已经成为行业重要的关键成功因素。

3. 适应敏捷开发流程的QA和测试部门

组织需要关注的第三个领域是适应敏捷开发流程的QA和测试部门。在敏捷和DevOps模型中,测试从中心部门转移到分散的团队。未来的测试组织需要将灵活性与效率和重用性相结合,提供测试环境、测试数据、测试专业知识和技能的测试中心将分散到各种业务线的IT团队。

QA和测试的现状与挑战

从调查结果,总结出以下关于质量和测试现状的发现:

1. 回归对应用程序质量的关注,表明在敏捷环境的新上下文里,测试已经成熟

面对开发和测试环境的复杂性以及数字化转型的速度,关注点正在回归到整体产品质量上来,这是一个进步的迹象:

  • 参与这次调查的受访者中QA和测试人员明显多于其他角色,由2016年的37%上升到2017年的41%;
  • 2016年被引用最多的目标是在上线前发现缺陷,这个数字从40%下降到2017年的28%;
  • 最终用户满意度从39%下降到34%。

客户体验和增强的安全性处于IT战略的前两位。从2016年到2017年,增强安全性需求从65%大幅下降到35%。 IT成本优化进入今年IT战略的前三位,证明QA和测试能够应对过去几年的快速变化。

其他一些对IT战略意义重大的领域包括对业务需求的响应、实施软件即服务以及实施敏捷和DevOps。敏捷和DevOps实施需求的减少幅度超过一半,从38%的受访者减少到17%,这表明这些开发方法正变得越来越主流。

2. 测试自动化正在通向智慧、智能和认知QA之路

自动化尚处于待开发阶段,测试活动的平均自动化水平约为16%。自动化产生的价值在很大程度上没有变化。测试自动化不仅应该复制现有的手动测试过程,38%至42%的组织将认知自动化、机器学习、自我修复和预测分析视为测试自动化未来的有前途的新兴技术。

智能解决方案是DevOps、移动和物联网中的新趋势。通过增加智能自动化,企业适应快速变化的业务环境能力将得到增强。

3. 敏捷开发中测试的挑战不断增加
  • 99%的受访者在敏捷开发测试中面临某种挑战
  • 46%的受访者认为缺乏数据和环境是最严峻的挑战,这比2016年的43%有所提高
  • 在敏捷迭代中重复使用或重复测试的难度排在第二位,由2016年的40%增加到了45%
  • 挑战数量下降的唯一领域是:难以确定测试的重点以及测试团队在计划或初始阶段的早期参与。

测试和测试环境的自动化将帮助组织解决敏捷和DevOps开发模式给测试所带来的大部分挑战。 这些智能测试解决方案使得质量保障的速度能够适应日益复杂的集成IT环境。

4. QA组织不断演进以满足双峰要求

2017年,集中式的测试组织和分散式模型之间的分配更加均衡。在许多组织中,以前的卓越测试中心(TCoE,Test Center of Excellence)已经过渡到更加灵活的测试卓越中心(TEC,Test Excellence Center),其重点在于支持和赋能,而不是实际执行测试活动。

瀑布式开发仍将在未来很长时间内实施,形成与敏捷和DevOps混合的局面。例如,组织选择定位软件开发测试工程师(SDET)的位置时,其中敏捷Scrum和TCoE分别是36%和47%。

5. 环境和数据仍然是QA和测试的难点

调查结果显示有73%的组织采用云环境、15%的组织采用容器化来执行测试,使得测试的生命周期缩短。然而,仍有50%上下的受访者分别表示在测试环境管理、测试环境利用率、适用于敏捷开发的开发和测试环境,以及早期进行集成的环境方面存在挑战。

在测试数据管理方面,分别有超过50%的受访者存在以下挑战:管理测试数据集的规模、创建和维护合成测试数据、遵守与测试数据相关规定。

6. 测试预算下降,但预计会再次上升

专门用于质量保证和测试的IT总支出的比例为26%,它已经从2016年的31%和2015年的35%下降。

但是,随着组织采用敏捷和DevOps来支持数字化转型,未来两年质量保证和测试预算将会增加,企业必须确保IT应用程序的数量和复杂性,以及随之而来的QA平台解决方案的质量。

推荐的应对策略

1. 提高智能测试自动化水平

自动化是满足日益增长的数字化转型测试需求的关键,建议组织制定一个中心战略,确定企业首选的测试工具,确定自动化计划的战略业务目标,并确定衡量结果的指标。

同时,引入基于分析的自动化解决方案,向智能化QA和智能化测试自动化转变,以确保能跟上数字化转型的速度,做到持续的发展。

2. QA和测试部门转型以支持敏捷开发和DevOps团队

首先是组织结构方面的转变,QA需要与Dev和Ops团队一起,构建集成的DevTest平台,以实现持续的测试自动化。

测试人员专业技能也需要有所改变,要加强开发、分析和业务流程方面的技术专长,以适应敏捷和DevOps模式。

3. 投资智能测试和质量保障平台

在日益复杂的IT环境下,智能测试平台有助于企业做好质量保障工作。

  • 将智能分析和机器人解决方案引入测试流程和平台;
  • 提高容器化和虚拟化解决方案的水平和使用;
  • 投资于测试数据生成解决方案,以提供更多更好的符合所有法规的合成测试数据;
  • 将容器化环境,虚拟化服务和自动化测试数据集成到一个共同的可访问流程和平台中,组织可以围绕所有测试活动制定一致的方法;
  • 采用持续监测,预测分析和机器学习工具,利用生产环境数据,提供基于业务风险和实际问题定义测试策略。
4. 定义企业级测试平台战略

开源和服务化解决方案给质量保障和测试工具的选择带来了灵活性,但是,跨多个存储库数据连接和交换导致企业级质量状态缺乏透明度。

企业可以实施单一平台战略,指定一些技术为主要选择工具,或者创建最佳工具策略,可以涉及来自不同供应商的多种工具解决方案。

5. 定义企业级QA分析战略

前面提到过智能分析是重点关注的领域之一。为了从智能QA(智能测试自动化和智能测试平台)的投资中获得最佳回报,建议组织确定企业范围的QA分析策略。

这种质量保证分析策略决定了应该部署分析和认知解决方案的目标和领域,定义了跨QA操作的智能技术路线图。质量保证分析战略应与整体组织战略相联系,并应描述其如何实现整个组织目标。

:以上内容和图片均摘自这份《World Quality Report 2017-1028》,更多详细内容请参考原文。

再谈敏捷QA

曾经在《敏捷中的QA》一文里介绍了敏捷开发模式下,QA如何参与从需求到测试的每个阶段,在每个实践中如何跟不同角色的合作,以及敏捷QA跟传统开发模式下的测试人员的区别等。

这些内容在今天依然适用,但在真实项目中往往情况比较复杂,总会听到一些困惑或者是质疑的声音。

在敏捷项目团队摸爬滚打多年以后,我想跟大家一起再来聊聊这个话题,下面逐个来分析我所见(听)到的质疑或困惑。

敏捷QA流程必须严格遵守

“如果QA没有参加Kick-off,我们拒绝做Desk Check;如果没有QA参与Desk Check,我们拒绝测试。”

从需求分析到生产环境,推荐QA参与每一个环节,跟多个角色进行充分的沟通和合作。

有人把这个当做圣旨,觉得不管怎样都不能漏掉某个环节,但难免有特殊情况。比如,由于QA请假或者开会等,错过了某一次Desk Check,一定要求等有时间了(甚至第二天或第三天)再补上,没准那个时候代码都已经上到测试环境,完全可以直接测试没必要在折腾大家来做一次全面的Desk Check了。

QA参与每个环节的目的是尽可能早期发现需求或者设计中的不足,做到Bug的预防。如果已经错过了这个“早”,那就没有必要再纠结非要严格进行每个环节了,不然不仅没有意义,还带来浪费。

QA不用了解太多的业务上下文,一样做的很好

“需求来的晚,QA手头忙着测试当前迭代的Story,根本没有时间去参与需求分析,不过这样也不影响,测好当前的卡就可以很好的保障质量了。”

这个想法是狭隘的。敏捷测试的原则之一是优化业务价值。如果连业务上下文都不清楚,如何做到优化业务价值?了解业务上下文的重要性不言而喻。

业务上下文

那么,真的忙的没有时间如何来破解呢?这其实是进入了一个恶性循环,需要找到突破点,打破这个不良环路,让其变成一个良性循环就好了。

不破不立,对于这个循环,就是需要减少测试Story的时间。可行的方案是:加强Desk Check,确保单元测试的覆盖,保证开发验收完成到最终交付的代码在自动化测试的保护下不被后续环节破坏;同时QA参与技术方案的设计讨论,这样测试的时候就可以有针对性的测,必要时候辅助以Bug Bash,由此节省出时间。经过两三个迭代的调整,情况定会有所改善。

技术方案讨论跟QA没什么关系

“技术方案,那是Dev们的事情,QA的重要任务是如何做好测试,参与技术讨论浪费时间。”

知己知彼,百战不殆。如果完全不了解技术实现,很难做到有的放矢。正如前面提到的,QA参与技术方案的讨论,了解更多技术细节,知道技术方案可能的风险,就能更好的指导测试,使测试更有针对性、更高效。

比如,对于微服务架构,了解了服务的熔断和降级机制,测试就能有效覆盖到相关方面。

单元测试Review没有价值

“单元测试还挺复杂,Dev新人写起来都不容易,QA更看不懂。QA Review单元测试,提不出有价值的反馈,感觉是在浪费时间。”

敏捷QA有个实践就是在做Desk Check的时候Review开发人员写的单元测试,其目的是两个方面:

  • 帮助发现漏掉的或者需要修改的测试,QA更好的了解测试覆盖情况
  • 帮助开发人员增加测试Sense,同时也能帮助QA提高代码阅读和理解能力

我理解对于单元测试Review的质疑是由于DEV和QA的相关技能还有所欠缺的情况下可能会发生的情况,但并不能因此否认这个实践的价值。

这时正确的做法是DEV跟QA解释每个测试所测到的内容,而QA从业务的角度考虑有哪些Case是遗漏掉了的。经过一段时间的磨合,我相信Dev的测试Sense和QA阅读代码、理解测试的能力都会得到提高。

必须严格Review每一个单元测试

“我对Dev写的单元测试总是不放心,不严格的Review根本不行。”

另一个极端情况就是,不管花多少时间,认为必须严格Review每个测试,认真的去检查测试的每个实现细节。

对于复杂一点的Story,严格Review每个单元测试,我见过最长的是花了两个小时,到最后大家都已经筋疲力尽…这显然是一种浪费!

QA Review单元测试更多的是关注测试的覆盖情况,而不是关注每个测试的实现细节,后者更多的是属于Code Review范畴。更重要的是,任何实践都不能只关注形式,要看其价值,具体问题具体分析。对于新的团队新的人,可能刚开始需要多花时间去了解所写的测试。而对于成熟的团队,或者是非常有经验的Dev,这个Review过程可以简化,只看测试的标题,或者只是听Dev说一下测试覆盖到了哪些内容就可以了。

我一般要求整个Desk Check控制在15分钟以内,对于特别复杂的Story,最多也不要超过30分钟。

没有发现Bug的测试不是好测试

“这些自动化测试从来没有发现过Bug,ROI太低,没有存在的必要!”

图片来自:https://www.netsolutions.com/insights/wp-content/uploads/2016/08/Why-You-Need-Automation-Testing-For-Mobile-Apps-Th.jpg

由于有些测试执行起来太耗时、测试实现成本和维护成本都很高,大家在讨论要不要去掉这些测试的时候,总能听到上面那样的声音。

其实,自动化的回归测试并不是用来发现Bug的,有数字表明自动化回归测试发现Bug的比例仅有15%。自动化测试只是形成一道保护的屏障,增加对系统质量的信心。

敏捷团队的QA对质量应该有全面的认识,在制定测试策略的时候需要综合考虑多方面因素,要真正理解每个实践、每个活动背后的真实价值。

敏捷QA该怎么做?

关于QA的定义,有下面三个层次:

  1. QA = Quality Assurance质量保障
    第一个层次QA的要求是做好质量保障工作,确保我们交付给客户的软件产品是正常工作的。
  2. QA = Quality Analyst质量分析
    第二个层次的QA通过测试、数据收集的方式,分析系统的质量,识别风险,并反馈给团队,和团队所有成员一起确保交付的质量是合格的。
  3. QA = Quality Advocate质量倡导者
    第三个层次的QA不再局限于只关注质量,通过培养对产品和流程持续改进的思维模式、了解产品的整体质量视图和持续关注产品质量的意识,引导整个团队构建正确的产品,并且正确地构建产品。

敏捷QA需要做到第三个层次,通过分析软件风险并制定相应实践,确保软件在其整个生命周期中持续工作并创造价值,为业务和团队提供信心,从而为客户提供价值。

敏捷QA的所有实践和活动都需要以价值为核心来驱动,根据不同团队的具体情况可以适当调整,且在不同项目阶段应该也是演进式的。敏捷QA跟各个角色的沟通和协作,也是随着团队成员的了解程度、配合默契度不同而有变化,并不是要求一成不变的。

微服务测试的思考与实践

最近几年,微服务架构越来越火爆,逐渐被企业所采用。随着软件架构的变化,对应的软件测试策略需要作何调整呢?本文将介绍微服务架构下的测试策略,并结合分享在业务和架构演变过程中,一个历经九年的项目测试策略的演进。

关于微服务

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,每个服务运行在其独立的进程中,服务间采用轻量级通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体的业务进行构建,并且能够被独立部署到生产环境、预生产环境。

从微服务的概念可以看出它有如下好处:

  • 每个服务可以独立开发
  • 处理的单元粒度更细
  • 单个服务支持独立部署和发布
  • 更有利于业务的扩展

同时,独立开发导致技术上的分离,HTTP通信加上Queue的机制增加了问题诊断的复杂度,对系统的功能、性能和安全方面的质量保障带来了很大的挑战。另外,服务间的复杂依赖关系带来了很多的不确定性,要实现独立部署,对运维也提出了更高的要求。微服务架构的系统要特别关注这几个方面:

  • 服务间的依赖、连通性
  • 服务的容错、可用性
  • 数据的最终一致性
  • 独立部署
  • 不确定性

测试策略的选择

谈到微服务的测试策略,很容易就想到了老马网站上Toby Clemson的文章《Microservices Testing》,该文推荐的微服务框架下的测试策略是这样的:

经典测试策略

这个策略模型强调测试分层以及每一层的恰当覆盖,整体符合金字塔结构。它是最优的吗?

有人对此提出了质疑…认为策略模型应该是蜂巢形状的(请参考文章):


这个模型重点关注服务间的集成测试,两端的单元测试和UI层E2E测试较少。

也有同事提出微服务下的测试结构应该是钻石形状的,服务间的集成依然是重点,单元测试较少,而顶层增加了安全和性能等非功能测试。

好像都有道理,到底选择什么样的策略模型好呢?不禁陷入了困境……怎么办?不妨先来听听我们项目的故事吧!

项目的故事

测试策略的演进

还是那个蓝鲸项目,不知不觉进入了第九个年头。在这九年里,随着业务的不断发展,系统架构也进行了多次演进和调整。相应的,测试策略也发生了有意思的演进变化。

测试策略的演进

最初单一用户系统、单体架构的时候,严格按照测试金字塔来组织各层的自动化测试。随着功能的扩展,大量mock的单元测试给重构带来了很大的不便。

企业系统开始开发的时候,我们调整了策略,减少单元测试的编写,增加UI层E2E测试的覆盖,测试结构由原来的金字塔演变成上面梯形下面倒三角的形式。

后来,架构调整,开始服务化。此时,大量的E2E测试渐渐暴露出问题:

  • CI上的测试执行时间越来越长,而且定位问题的能力很弱,测试一旦失败需要很长时间修复,测试人员好几天也拿不到可以测试的版本,反馈周期过长;
  • 由于服务化带来的不稳定因素增加,E2E测试没法很好的覆盖到需要的场景,测试人员就算拿到可测的版本也总有各种缺陷发生。

因此,项目引入契约测试,停止编写新的E2E测试,将测试下移,分别用API测试和契约测试取代。

随着功能的不断增加,虽然E2E测试的量并不增加,但是其不稳定性、维护难、定位难的问题有增无减,此时已经很难由自动化测试来保证产品的质量。为了平衡成本和收益,项目考虑去掉大部分E2E测试,只保留少量的Smoke测试,将更多的测试下移。

同时,技术雷达上新的技术“生产环境下的QA”出现,项目也开始关心生产环境,并且在QA测试阶段结合微服务的特点进行对应的探索式测试。

应对微服务的挑战

前文提到过微服务带来的挑战,下面来看项目是如何应对这些挑战的。

  • 服务间的依赖、连通性

微服务架构下,独立开发的服务要整合起来最具挑战,如何保证服务间的依赖关系和连通性非常关键。前面已经讲过E2E集成测试有很大的挑战,并不适合,而消费端驱动的契约测试是个不错的选择。项目正是利用契约测试去保证服务间的连通性,取代一部分E2E集成测试。

  • 服务的容错、可用性

在系统负荷达到一定程度或者某个服务出现故障的时候,微服务架构有两种技术来确保系统的可用性:服务的熔断和降级。服务的熔断是指当某个服务出现故障时,为了保证系统整体的可用性,会关闭掉出现故障的服务;服务的降级则是当系统整体负荷过载的时候,考虑关闭某些外围服务来保证系统的整体可用性。

对应的测试包括:

  1. 熔断:从性能角度,当系统负载达到某个熔断状态的时候,服务是否能正确熔断;同时,从功能角度验证熔断后系统的行为是否跟预期相符;
  2. 降级:从业务的角度,要能区分出核心业务和外围业务,在需要降级的时候不能影响核心业务;当某个服务降级后,从功能角度验证系统行为是否跟预期相符。
  • 数据的最终一致性

数据一致性是微服务特别需要关注的。举个例子,电商平台某个订单支付成功以后,需要更新积分和订单状态,当订单服务或者积分服务其中有一个出现故障的时候,就会导致最终的数据不一致性。

测试这种情况,从业务的角度分析哪些服务会导致数据不一致性,制造对应的异常情况去测试数据的最终一致性。

  • 独立部署

微服务的独立部署需要有CI、CD的支持,跟DevOps实践分不开。同时,更为关键的是需要契约测试来验证独立部署后服务行为的正确性。项目在这方面的工作,请参考王健的文章:你的微服务敢独立交付吗?

  • 不确定性

微服务架构使得系统复杂度增加不少,很多的事情发生都是不可预测的,只能在其发生以后找到产生的原因。因此,也就没法在预生产环境通过测试去发现在真实生产环境才会发生的issue,我们需要把目光转移到生产环境,利用生产环境的不确定性、微服务的不可预测性来构建反脆弱的系统。

项目在这方面主要采用的技术是生产环境下的QA,请参考文章:生产环境下的QA

项目测试策略

从前面介绍的演进过程可以看到,项目测试策略在不同阶段结合参考了不同的策略模型:金字塔->近似钻石(除非功能测试外,类似于钻石模型)->蜂巢。后期全面服务化的时候,我们认为蜂巢模型是比较适合的。

当然,光有符合这个策略模型的自动化测试是远远不够的,我们项目还采用了针对微服务特点的探索式测试,保持持续交付节奏,践行DevOps实践,结合生产环境下的QA等技术把关注点右移到生产环境。

现在,项目整体测试策略演变成下图的形式:

  1. 项目采用的是敏捷迭代开发和持续交付的模式,每四周一个发布周期。
  2. 在开发过程中实现的自动化测试是分层实现的:底层少量的单元测试,中间量最多的是API测试(类似于老马推荐的策略模型里的组件测试),上面有一部分契约测试和少量的Smoke测试来保证服务间的契约和集成。除此之外,QA有手动的探索式测试,其中包括针对微服务特点进行的一些测试。整个测试结构是类似于蜂巢模型的。
  3. 采用生产环境下的QA技术,利用生产环境,进行error监控、用户行为分析、用户反馈收集,从而来影响和指导预生产环境的开发和测试工作。
  4. 利用DevOps实践,做到高效的部署和监控,跟生产环境下的QA结合,形成良性的环路,保证项目的正常交付。

测试策略再思考

项目上多次测试策略的调整,看似很简单,其实每次调整并不是一个轻松的过程,都是平衡利弊、综合考虑多个因素才做出的决定。

分析整个调整过程,最后突然发现:当我们面对多个策略模型不知道如何选择的时候,其实我们陷入了一个太过于关注测试结构的误区,忘记了最初的目标是什么。

影响测试策略的因素

跳出误区,回到原点,重新思考测试策略的目标。影响策略的最关键因素是业务价值、质量要求、痛点。

  • 业务价值

带来更大的业务价值、帮企业赢得更多的利润,是软件系统的目标;软件测试是软件系统成功的保障之一,业务价值也是测试策略的终极目标。所有测试活动都要围绕这个目标开展,考虑业务优先级,有效规避业务风险。

  • 质量要求

不同的系统、同一系统的不同利益干系人(参与的不同角色)对于质量的定义和要求都可能是不同的,这毫无疑问是影响测试策略的一个关键因素。

对于仅有内部用户的系统,关注的重心可能是系统的功能;而对外发布的产品,则要求更高,一个按钮位置的不恰当都可能带来大量用户的流失。

  • 痛点

真正的痛点往往也是优先级最高,迫切需要解决的。那些可以通过测试策略的调整来解决的痛点,自然成为了关键的影响因素之一。比如,CI Pipeline出包太慢,为了提高出包的效率,一方面在Pipeline本身想办法,另一方面调整自动化测试的比例、执行频率等也是解决方案之一。

演进式测试策略

处在不同阶段的项目,在业务价值这个大目标下,其他影响因素也是会不一样的,跟技术架构的演进一样,测试策略也应该是演进式的。

从目标出发,综合所处阶段各个方面的影响因素,制定出适合当时的测试策略。随着时间的推移,对策略进行评估和度量,并进一步改进、提高,以更好的满足需求。这就是目标驱动的演进式测试策略。

总结

微服务架构下多个服务的整合是最具有挑战的,对此最重要的是契约测试。契约测试有效保证服务间的契约关系不被破坏,确保服务的连通性,有助于实现真正的独立部署和独立交付。

微服务架构引入的不确定性并不是坏事,可以利用这些不确定性,采用生产环境下的QA等技术,增强系统的反脆弱性,从中获益。

测试策略的影响因素不是唯一的,技术架构并不是最关键的因素。微服务架构下的测试策略跟其他架构下的并不会有本质的区别。

业务价值始终是我们的终极目标。在这个终极目标的驱动下,测试策略不是制定完了就可以束之高阁的,需要在整个软件系统构建过程中不断的度量和改进,是演进式的。

聚焦测试,驱动卓越

在经历了“七年之痒”后,蓝鲸项目进入第八个年头,项目的一切趋于稳定。团队倡导持续改进,可大家的感觉是已经尽力做到最好,这个时候似乎没有什么可以改进的了。为了突破这个局面,项目重新聚焦测试,从质量和测试的角度对现状进行了一次评估。

评估采用的是基于软件测试原则的模型,本文就是跟大家分享一下这个模型。

测试原则

Testing principles

2012年澳大利亚敏捷大会(Agile Australia)上ThoughtWorks的非常资深的测试实践带头人Kristan Vingrys分享了如上测试原则,这些原则是ThoughtWorks的同事们在多年软件测试经验基础上总结出来的。

1. 质量内建(Build quality in)

You cannot inspect quality into the product; it is already there.
— W.Edwards Deming

著名的质量管理专家戴明指出:产品质量不是检测出来的,从产品生产出来后质量就已经在那了。这同样适用于软件产品。

缺陷发现的越晚,修复的成本就越高。质量内建要求我们做好软件开发每个环节,尽早预防缺陷产生,以降低缺陷出现后的修复成本,要减少对创可贴式的补丁(hotfix)的依赖。

Cost of change

推荐实践: TDD、ATDD等

2. 快速反馈(Fast feedback)

每个环节的任何变化都能最快的反馈给需要的人,从而可以基于当下最新信息做出明智的决定,降低风险。这要求我们对系统进行频繁的测试,缩短回归测试的周期。

推荐实践:

  • 符合测试金字塔结构的自动化测试,让每一层的测试都能发挥尽可能大的价值,给出最快速的反馈;
  • 持续集成,尽早排查集成引起的问题,降低集成所带来的风险。
3. 全员参与(Involve everyone)

— 这次上线好多bug,QA是怎么测的?!
— 那个xxx组在上线前发现了很多的bug,他们的QA真给力!

成也QA,败也QA…如果还是这样的认识,那是极为片面的。测试不仅仅是QA的事情,团队成员要一起为质量负责,软件开发生命周期的测试相关活动需要全员的参与。

全员参与的好处是利用不同角色的不同领域知识和不同的思维模式,不仅可以使得测试的质量更高,同时还能最优化利用测试资源,做到价值最大化。

推荐实践:

  • 自动化测试:QA和BA结对用DSL编写测试用例,QA和Dev结对编码实现测试,生成业务人员可读的测试报告;
  • Bug bash(bug大扫除):团队不同角色一起参与的一个找bug的测试活动
4. 测试作为资产(Tests as asset)

自动化测试帮助我们验证系统功能的正确性,好的自动化测试还有文档的功能,是宝贵的资产。如果每个项目都构建自己独立的自动化测试,没有跨项目共享,其浪费显而易见。

这个原则要求把自动化测试的代码跟产品开发的代码一起,当做资产管理起来,在不同项目间做到尽可能的复用。这笔宝贵的资产能帮助我们更好的统计跨项目的测试覆盖率,更好的优化测试。

推荐实践:利用版本控制管理工具把测试代码和产品构建代码一起管理,都作为产品的一部分。

5. 更快的交付(Faster delivery into production)

任何一个idea越快做成软件产品交付给用户,给企业带来的价值越大。

该原则要求我们把测试活动融入软件开发生命周期的每个环节,不要在后期进行长时间的集中测试;同时测试人员的关注点不再是发现更多的bug以阻止不符合质量要求的产品上线,而是把目标放在如何能够帮助团队尽快的让产品上线,让企业投资回报更早,也就是更快的赚钱。

推荐实践:自动化构建流水线、关注平均恢复时间、发布与部署解耦等。

Pipeline
6. 清晰一致的测试视图(Clear and consistent view of testing)

可视化的报告给客户和内部团队展示测试的状态和产品内外部的质量,对项目的质量和风险把控是非常有帮助的。不同项目各自采用五花八门的图表样式,将不利于项目间的信息共享和比较,无端增加复杂性,带来浪费。

因此,我们需要把状态报告做的尽可能简单、清晰,并且保持跨项目的指标一致性;同时,我们不应该为了让某个指标变得好看而改变我们的行为,整个报告要诚实开放,这样才能真实反映出项目的状况。

7. 优化业务价值(Optimize business value)

开发软件无疑是要给客户的业务带来价值,软件测试也需要为这个目标服务,测试要跟业务价值保持一致,帮助客户优化业务价值。要求做到:

  • 测试不仅是保险,不仅是保证软件质量的;
  • 要有目的的关注变化的特性,不要盲目的散弹枪式的对任何特性进行测试,要有优先级;
  • 要能帮助企业驱动新的特性和功能;
  • 帮助客户创造安全的尝试新点子的环境,提供快速的反馈。

推荐实践:

  • 基于风险的测试,根据业务优先级需要调整测试策略,在测试过程中尽可能规避给业务带来的风险;
  • 生产环境下的QA,通过收集生产环境的真实用户行为和应用使用数据,对业务的优化做出贡献。

评估模型以及在项目中的应用

评估模型就是将上述七条原则的每一条细化,列出该原则对应的实践和行为,并给每个实践或行为设定0-5分的不同评分标准,最后统计各个原则的总分,形成类似下图的结果报告:

Result Model

在项目中的应用

以Cristan分享的模型为基础,由Tech Lead和几个DEV、QA成立一个评估小组。

第一步:分别根据各自的理解给项目打分,结果是很有意思的,请看下图:

结果对比图

根据这些结果,可以看出大家的认识是不太一致的。

第二步:评估小组对模型中的每条细节进行review,做适当修改以更符合项目情况,并且在评估小组内大家达成共识。其中,所做的修改包括修改原有的实践评分指标、增加新的更适合项目和当前技术趋势的实践、删除过时的或者不符合项目特点的实践。

第三步:根据更新过后的模型指标对项目上的一个Team做评估试点,详细分析该team对应到测试原则各个维度的well和less well部分,由评估小组成员一起打分,得到该team的评估结果图。

第四步:根据评估结果并结合项目目标排定需要改进的优先级,制定出改进action,并更新给试点team执行。

后续:试点一个周期后再次评估,并重新review评估模型,再推行到整个项目。同时,周期性的进行新的评估和制定新的action,以做到持续的改进和优化。

总结

图片来自网络

应用程序的质量、测试的快速性、以及上线后轻松自信的更新服务的能力,是帮助企业业务价值最大化的关键因素之一,一直是我们所追求的。

基于测试原则的评估模型,可以帮助我们在追求这个目标的道路上少走弯路,帮助我们持续的改进,以驱动出更加卓越的软件。

物联网测试地图(译)

物联网的出现,给测试带来了很多有意思的挑战,使得众多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在测试同一个物联网产品的团队,地图可以作为大家共同参考的手册。这个地图把工具、设备、场景和协议的排列以易于理解的方式呈现出来,覆盖了测试场景设计这个独特的需求,是一种非常高效的合作方式。


  1. 此文发表于:TW洞见
  2. 英文原文请参考:IoT Testing Atlas

系统级集成测试的断舍离

食之无味,弃之可惜

在企业级应用的季度或月度发布被认为是领域最佳实践的时候,应用部署到生产环境之前维护一个完整的环境进行集成测试是非常必要的。但是,集成测试环境和集成测试本身有着如下的问题:

  • 环境本身脆弱,而且通常存在手动配置部分,环境维护成本很高;
  • 环境因素导致集成测试不稳定、不可靠、反馈慢,测试失败不易定位问题,同时还会重复测试隔离组件已经测过的功能。

集成测试成为了持续交付的瓶颈,犹如鸡肋。因此,最新一期(2017年第16期)ThoughtWorks技术雷达建议企业暂缓搭建企业级集成测试环境,而是采用增量的方式发布关键组件到生产环境。增量发布涉及到一些重要的技术包括契约测试、将发布与部署解耦、专注于平均恢复时间和生产环境下的QA 。

技术雷达之集成测试

断舍离之技术可行性

下面分别介绍技术雷达建议的这四项技术,以及在没有集成测试的情况下如何保证应用的质量、如何帮助企业做到独立增量发布。

消费端驱动的契约测试

消费端驱动的契约测试是微服务测试的重要组成部分,主要用来覆盖两两服务之间的契约关系,下面举个例子来说明什么是契约测试以及契约测试与API测试的区别。

插头与插座

家里有个插座,买电器的时候需要考虑插头跟插座是能配对的,也就是说插座和插头之间需要有契约。

这里的契约测试就是插座跟插头的配套性测试,包括

  1. 三相/三头还是两相/两头的;
  2. 电压是220V还是 110V;
  3. 插孔的形状:英式?中式?
  4. 等等

API测试:对于插座本身功能的测试,需要覆盖

  1. 插座能够正常通电;
  2. 电压是预期的220v;
  3. 接地的插孔真的能够接地
  4. 等等

也就是说API测试需要测试API本身功能的各个方面,而契约测试重点在覆盖API调用的格式、参数数量、参数类型等,不一定需要涉及API本身的功能和具体的数据。

更多关于消费端驱动的契约测试,请参看文章《Consumer-Driven Contracts: A Service Evolution Patter》。

发布与部署解耦

部署,就是把组件或者基础设施部署到生产环境,不对用户可见,不会影响业务和用户的使用。发布,则是将部署的组件让用户可见,对业务会产生影响。可以通过采用Feature toggle的方式实现部署与发布的解耦,做到持续部署和可控制的发布,减少组件改变带来的风险。这样,产品经理可以根据业务需求灵活控制发布给最终用户的功能组件,帮助企业业务价值最大化。

关注平均恢复时间

先看这样两种情况,思考哪种更好:

  1. 系统宕机次数很少,可能每年也就一到两次次,但是恢复能力很弱,一旦宕机,得花至少24个小时恢复正常;
  2. 系统宕机频率较高,不过每次宕机都能快速恢复,用户甚至感觉不到。

对于第一种,平均失败间隔很长,但是一旦失败对用户的影响不言而喻;第二种虽然有频繁的失败,但是平均恢复时间很短,用户体验不受影响,当然是第二种更好。

传统的Ops团队比较关注失败发生的频率,随着持续交付和监控技术的发展,快速恢复成为可能。不用担心错误、失败的发生,而是利用对这些错误和失败的监控和分析,让系统做到快速恢复,可以省掉一些复杂的集成测试,也可以减少无处不在的安全攻击的影响。

生产环境下的QA

生产环境是真实用户使用的环境,通常都不能跟测试环境那样可以在上面直接测试产品的功能,不能简单的把测试环境所用的的QA技术直接后延到生产环境,而其中一项在生产环境使用的技术就是监控。采用监控技术来获取生产环境的信息,对其进行分析,然后优化开发、测试过程,同时优化企业业务。更多关于生产环境下QA的内容,请参看文章《生产环境下的QA

对上面四种技术的解释,我们可以看到:契约测试是对持续独立部署有帮助的,监控技术则是缩短平均恢复时间和做好生产环境下的QA共同的关键技术之一。接下来主要分享项目在围绕契约测试和日志监控这两块所做的实践,一起来看系统级集成测试的断舍离该如何实现。

断舍离之项目实践

项目是一个开发了七八年的老项目,团队对集成测试也是进行了多次的调整,经历了“七年之痒”后依然觉得是鸡肋:

  1. pipeline上执行非常不稳定,总是“随机挂”,不能真实反映问题;
  2. 系统复杂,集成测试自然也不简单,每次顺利执行的时间都需要半个小时以上,何况还有很不稳定的情况,最严重的时候导致QA超过一周拿不到包部署;
  3. 通过集成测试发现的应用程序的缺陷半年也难得出现一个;
  4. 随着系统逐渐变得复杂,集成测试维护的成本也不断增加。

可以看出,集成测试已经严重阻碍了项目持续交付的进行,不得不对其断舍离了。

(一)测试策略调整

断舍离的第一个部分是从集成测试本身入手,调整测试策略。步骤如下:

  1. 不再添加新的功能层面的自动化测试,原有的集成测试部分能用底层的UT、API测试覆盖的尽量下移;
  2. UT和API测试不能cover的服务间的契约关系通过增加契约测试来保证;
  3. 从CI上摘掉原来的集成测试,加速pipeline出包,然后添加Smoke测试到QA环境执行;
  4. 不管是在测试环境还是生产环境发现缺陷,则添加对应的测试。

整体策略调整思路是根据测试金字塔的结构进行调整,把测试尽量往下层移,但并没有全部去掉集成测试,只是缩减到非常关键的路径覆盖,最终测试结构调整如下图所示:

项目测试金字塔

(二)日志监控、分析和优化

没有了Pipeline上的集成测试,直接上到QA或者prod环境,那么加强日志监控变得尤其重要。因此,断舍离的第二个部分是日志的监控、分析和优化。

**日志数据采集 **
项目使用的日志分析工具是Splunk,使用该工具从下面几个方面来着手采集日志数据:

  1. 在Splunk上设置日志监控的Dashboard,主要用来监控API的请求失败、错误的日志,还有API执行时间等性能相关内容。如下图所示:
监控Dashboard
  1. 设置预警邮件提醒:对于一些存在严重性能问题的API请求,通过邮件的方式进行预警提醒,如下图:
预警邮件
  1. 主动查找错误日志:对于一些生产环境用户反馈回来的问题,通过主动查找错误日志的方式去定位。
  2. 前面的几个机制同样应用于QA和Staging等测试环境,以通过日志分析尽量提前发现问题。

日志数据利用

利用前面几种方式采集到的日志数据,从下面几个方面进行分析和优化:

  1. 发现和定位系统功能问题,分析系统用户的行为习惯,优化业务;
  2. 发现和定位安全、性能等非功能问题,进行修复和优化;
  3. 发现和分析日志记录本身的不足,规范日志记录,从而进一步增强日志给问题诊断带来的帮助,形成良性循环。规范日志记录主要涉及这些点:统一日志输出路径、统一日志记录格式、清晰定义日志级别,并且把添加必要日志作为story开发流程的一部分,QA会参与日志评审。下图是Splunk里看到的项目最新优化的日志记录格式:
日志

项目对集成测试断舍离才刚刚开始,正在不断摸索着前进,目前能看到的最直接的影响是pipeline出包明显加快,由以前的好几天出不来一个包变成一天能出好几个包。最让人振奋人心的是本周刚刚发生的事情:前一天下班前报的bug,第二天上午就已经修复出包可以测试了。

写在最后

系统级集成测试虽然有各种问题,不一定会因为集成测试挂掉而发现很多问题,前面也讨论了断舍离的可行性,分析了项目断舍离的实践,但集成测试并不是用来发现问题的,而是一道对质量把关的屏障,关键路径的必要测试是不可替代的。因此,我们提倡减少集成测试的数量,合理调整各层测试的比例。

系统级集成测试的断舍离需要团队有持续、递进、稳定的交付能力,需要保证用户不会受此影响,企业业务能够正常运转。系统级集成测试的断舍离过程不是一蹴而就的,凝结在集成测试上的心血也不是那么容易放弃的,需要很多的平衡和取舍,并在整个过程中要不断的关注系统的质量和风险,及时作出相应的调整。

为什么不能每周发布一次?

图片发自简书App

“看,车来了!不过这趟车貌似咱赶不上了吧?!”
“啊!那快点跑,错过这趟就得再等半个小时!”
……

好无奈,可是真的赶不上也没有办法,这个场景很多人都经历过。

“这个release又是一定包就开始上hotfix,四天跟了四个,我根本没时间做回归测试!” QA小静同学抱怨道。
“每次都是定包后就开始无休止的上hotfix,咱们还不如改成每周发布一次!”Dev大鹏同学也被hotfix折磨苦了。

这是发生在蓝鲸项目的一次真实而平常的对话,跟前面赶公交车的场景有什么关系呢?

发车间隔与发布周期

发车间隔的不同带给乘客的感受会完全不同。

有些公交车很少,每半个小时一趟,有时候眼看着一辆车来了又走了,没赶上的心情无比懊恼,下一趟还得等上半个小时啊!实在着急的可能考虑叫一辆快车赶紧走…

而有些公交车发车间隔非常短,几分钟一趟,就算错过一趟也无需等待太久,只要不是着急去救火的乘客一般都不会太在乎。

图片发自简书App

项目的不同发布周期带给客户的感受也是类似的。

蓝鲸项目的发布周期跟第一种公交车发车间隔非常类似,是四周发布一次,如果这次没能上线的功能,或者有导致功能不能正常工作的缺陷,下次发布上的话,就得再等一个月。一个月,那是多少白花花的银子啊!对于那些特别重要的功能,客户着急就要求上hotfix,于是就出现了前面小静和大鹏对话中的场景。

Hotfix是否真的能解决软件交付过程中的问题呢?其实不然。

Hotfix的引入带来很多额外的工作,影响新功能的按时交付,会打乱交付节奏,从而有形成恶性循环的趋势。既然这样,大家一定希望能解决,而且通过公交车的例子很容易想到前面大鹏说的那个方案。

如果发布周期缩短,比如说一周甚至更短,这次没上的功能也不用那么着急的通过hotfix来上线,就能解决问题。那么蓝鲸项目为什么不一周发布一次呢?

如何才能缩短发布周期?

发布周期的影响因素

1. 合适的迭代计划和合理的需求切分

半个小时一趟的公交车,就算车子足够大能够承载半个小时到达的乘客数,可是会导致乘客等待时间过长,造成很多不便和耽误。要解决这种情况,可以把大型公交车换成多辆小型车,增加发车次数,缩短发车间隔。发车间隔缩短到多少,车子换成多大的都是需要仔细分析和考虑的问题。

映射到蓝鲸项目,要缩短发布周期,就得有相应的小规模需求正好能够乘坐小发布周期那样的小车,要做好发布计划和需求切分。

这样,对需求源的要求很高,需要客户那头的紧密配合。要想缩短发布周期,首先必须得有足够的、粒度合适的功能需求,能够正好安排到较短的发布周期上线。如果需求范围不能提前确定好,就没法提前做好短周期发布计划,不可能把发布周期缩短。

2. 强大的开发能力

乘客的需求分析清楚了,要想缩短发车间隔非常关键的一点就是要有足够的安全的车和靠谱的司机。 如果这一点满足不了,其他都免谈。

对应到蓝鲸项目,安全的车子和靠谱的司机组成了团队强大的开发能力,包括架构支撑和人员技能。

车子就是对持续交付友好的技术架构,需要减少模块间的依赖,比如采用微服务。蓝鲸项目是一个七年之久的老项目,很多陈年依赖已经形成,要拆分不是一时半会的事情,团队正在朝着这个方向努力。

司机就是我们的开发团队,除了要有必要的开发技能外,要做到靠谱就得透彻理解持续交付的精髓,需要团队人人都有质量意识,人人都有发布周期的紧迫感,并且能够做到高效合作,从需求划分、代码质量、测试保障等做好各个环节的工作,做好缺陷的预防和监控,不让严重缺陷流入后面阶段。

蓝鲸项目由于新人较多、人员流动大等原因,对于质量意识和紧迫感都有待提高。 不过,在各位QA的影响下,团队人员的质量意识、紧迫感都在改善,新人的技能也在不断的学习和实践中得到提高,但仍然不能放松警惕,需要时刻保持向前的精神面貌。

3. 充分必要的测试支撑

有了足够的安全的车和靠谱的司机,还得保证路况足够好,这样才能做到不管到达哪个站,间隔都是相同的。

要想蓝鲸项目的持续交付能够顺利前行,一路畅通,需要严格做好质量内建,各层都有充分必要的自动化测试保护,减少新功能开发过程中对老功能的破坏;同时持续集成流水线也要很健全,不能耽误代码提交和出包,从而影响开发和测试的进度。

蓝鲸项目开发年限已久,复杂度很高,在持续交付的路上行走的有些坎坷。目前团队正在这些方面努力采取改进措施,取得了不少进展,但确实还有不少提高的空间。

前景堪忧?

图片发自简书App

过去七年,蓝鲸的持续交付之路有些坎坷,但不应因此而失去信心。

通过跟公交系统的对比,我们可以看到蓝鲸项目要缩短发布周期、杜绝hotfix,需要从需求切分、迭代规划、技术架构、团队能力和测试策略等多方面进行优化,才能保证持续、快速的发布节奏,这是一个系统的问题。

七年之痒已经平安度过,蓝鲸团队正在采取相应的改进措施,一旦做好了上述各方面的优化,相信下一个七年一周发布一次或者更短发布周期都将不是梦!

大规模团队的QA如何高效合作

“你们团队QA和DEV的人员比例是多少?”
“我们团队一般有1个QA和3~4对DEV pair.”

经常会被问到这样的问题,一般的小团队都是这样的人员比例,QA也不会觉得压力有多大。当多个特性团队工作在同一个代码库、分别在开发同一个系统的不同功能的时候,虽然每个特性团队也保持前面所述的比例,对于QA的挑战却要大得多,那是因为:

  • QA不仅要了解自己特性团队的需求,还需要了解其他团队的需求,因为这些功能都在同一个系统上,联系必然是很紧密的;
  • 某个团队发现的软件缺陷的根源、错误日志信息,在其他团队也可能发生,这些信息需要共享;
  • 某个特性团队有任何基础设施、测试环境配置文件的变化都得让所有团队知晓,而QA是其中沟通这个内容最恰当的角色;
  • ……
图片来自网络
(图片来自网络)

由此可见,大规模团队的QA不像小团队那么简单,沟通的成本要高很多。如果没有及时沟通,将会造成信息不对称,要补救所花费的额外精力是比较大的。当然,大规模团队不仅QA的沟通成本增加,其他角色也一样,只是因为我是QA嘛,就跟大家聊聊我们QA是如何应对这种大规模团队的挑战的。

集体参加story的kickoff和desk check

不管哪个组有kickoff和desk check,各组的QA都一起参加,这样基本能搞清楚各个团队都在开发什么功能。只有两三个特性团队的时候,这个方法还勉强行得通。但随着团队越来越多,在高峰期的时候,QA可能一天都在这两个活动中切换,通过这种方式了解各组的需求似乎不是一种高效的方式……

集体参加各组的feature kickoff

一个release做一个feature的话,QA参加feature kickoff每个release只需要参加一次,貌似还可以的样子。但由于各组的发布周期是一样的,各组做feature kickoff的时候,QA正是忙着上一个发布周期验收测试的收尾阶段,同时也是忙着review自己所在特性团队story的时候,一般都比较忙,尤其特性团队越来越多,如果还要集中参加其他组的feature kickoff,一定会忙不开……

前面这两项我们团队都有实践过,但显然都没能很好的坚持,因为手头的确有些忙不过来,这些自然优先级就变低了。大家始终坚信信息共享的重要性,于是团队在不断摸索中找到以下两种方式。

定期catch up

定一个每周一次的例会,要求QA们合理安排手头工作,务必参加该例会。例会上每个人
给大家介绍自己组内的feature,更新状态,把遇到的困难、blocker、风险等拿出来跟大家一起讨论,讨论对策,并且对一些接下来要做的事情清晰列出来,找到专人own,下次例会的时候检查执行情况。

QA内部showcase

在每个发布周期,在QA们做一次showcase,共享组内新开发功能特性。这样不仅锻炼了QA做好showcase的能力,同时也给其他团队QA共享了业务功能信息。

这两项实践以来,大家感觉到的收益还是蛮大的,除了知识、信息共享之外,也增进了QA间的相互了解,对于大家一起合作带来很大的帮助。

当然,除了这种具体的实践,更重要的是大家都有一颗愿意分享的心。随着例会和内部showcase的开展,QA们共享信息的意识得到了加强,日常工作中遇到某种情况觉得其他团队需要知道的就会主动分享出来。

大团队带来的挑战不是那么轻松容易解决,关于如何能高效协作,我们也还在继续摸索中。

不知道您所在团队是否也面临如此挑战?是否愿意和我们大家一起分享分享呢?

神圣的QA——写给应届毕业生

你有没有过下面的经历:

  • 在谷歌浏览器输入一个网址,出来一个错误提示:“不支持当前浏览器,请用IE访问”…
  • 换成IE,重新打开该网站,输入用户信息注册一个新用户,随后收到一封注册成功邮件,里边直接包含刚刚注册的密码…
  • 用注册的用户名密码登录进去,又不知道所需要的功能入口在哪里…
  • 翻遍了一层又一层的菜单,终于找到了入口,进去打开的是一个列表,足足等了2分钟才加载完成…
  • 从列表中找到自己需要的那个信息,点击“查看详情”,却显示一堆乱码…
这么多问题 :(

一次性碰到上面的各种当然属于极端现象,但我敢说,你一定碰到过其中的问题不止一次,而且碰到了一定很郁闷。这些都是软件缺陷,分别是兼容性、安全性、易用性、性能和功能方面的缺陷,一旦出现将会给企业和用户带来不同严重程度的影响。

这种糟糕的体验有没有使你产生想去优化的冲动?你是否想知道如何帮助软件开发团队开发出缺陷更少的软件产品?如果你的回答是肯定的,那么请跟我一起来做QA吧:)

QA是什么?

狭义的理解就是软件测试,软件测试工程师常被称为QA;广义上,QA就是在软件开发过程中做好软件质量分析和保证的人员。

QA的职责有哪些?

QA的职责

下面结合一个简单的例子说明QA的职责:生产杯子。

1. 理解和澄清业务需求

需求是软件开发的源头,需求的正确性、合理性对软件开发的质量有着至关重要的作用。QA的一个很重要的职责就是澄清需求、验证需求合理性,并且帮助团队一致理解需求。

需求包括功能需求,也包括各种非功能需求:性能、安全、易用性、兼容性等。所谓理解和澄清业务需求,就是需要把业务相关的功能和非功能需求都搞清楚了。

对于生产杯子的例子,QA需要搞清楚杯子的功能有哪些:普通的盛水、加热、保温、带吸管等等。杯子的功能可能还远不止这些,这就需要发散性思维,去挖掘可能得用途并进行确认、测试。除了功能需求以外,还有要考虑的非功能需求可能有:材质耐热性、耐摔性、跟各种液体的兼容性、安全性(是否有毒?是否可以砸伤人?)……

注意

需求的澄清是个过程,并不是在开始开发和测试之前要搞清楚所有的需求(这也是不可能的),同时可以在开发和测试过程中不断去澄清需求、优化业务流程。

2. 制定策略并设计测试

澄清了需求,还得知道怎么去验证软件产品是否满足了需求,这就需要制定测试策略,并根据策略设计测试。大概说来,需要确定测试范围、测试阶段,覆盖要求的测试范围都需要什么类型的测试(功能与非功能等),在每个阶段采用什么测试方法,手动测试和自动化测试的分配比例,如何设计手动和自动化测试的测试用例,用什么工具实现功能、性能和安全测试的自动化等。

对于杯子来说,确定需求之后,针对每一项需求指标需要确认可能采取的不同测试方法,需要考虑如何测试盛水和加热功能、如何测试耐摔性(直接摔吗?)、以及如何测试安全性等等。

可以参考测试四象限测试金字塔等模型来制定测试策略,并根据产品发布周期制定具体的测试计划、设计测试内容。

注意

设计测试,不仅是指设计测试用例。
四象限和金字塔只是个参考,不可以生搬硬套,而且有些内容稍有争议,但参考价值还是很大的。

3. 执行和实现测试

根据制定的测试策略和测试计划、设计好的测试用例,执行手动的验收测试和探索式测试等,实现和执行功能和非功能的自动化测试,统计和生成测试结果报告。

对于生产的杯子,根据设计的测试方案对产品(半成品)进行测试,可能的方式有:往里加水,直接摔到地板上,加热至100摄氏度,往里注入硫酸等。测试之后,统计和生成杯子的测试结果报告,内容包括但不限于测试样品集、测试方法、测试结果、成功率等。

4. 缺陷管理

测试之后,必然会发现很多的缺陷,对这些缺陷进行有效的管理是QA们一个非常重要的职责之一。缺陷管理包括以下内容:

  • 记录缺陷
    发现缺陷以后,QA需要尽自己所能去调查缺陷,收集所有跟缺陷相关的信息,包括不限于出现的环境(操作系统、浏览器和不同的测试环境等)、重现步骤、屏幕截图、日志等,并将这些信息简单清晰的记录下来。
  • 确定严重性和优先级
    严重性是指缺陷发生对用户所产生影响的严重程度,优先级是指需要修复的紧急程度,通常需要结合严重性和发布计划等来确定。新QA往往比较容易混淆这两个概念,注意它们是有区别的,优先级高的严重性不一定高,而严重性高的往往优先级比较高。具体需要根据产品和项目实际情况来确定。
  • 分析和跟踪缺陷
    开发人员修复缺陷之后,QA需要测试和验证缺陷,很多时候缺陷被验证之后就没人管了,但缺陷的生命周期并没有结束,后面还有非常重要的分析和跟踪阶段。在这个阶段,QA要分析缺陷产生的原因,影响的功能模块,过去一段时间以来的发展趋势等,根据这些分析结果制定下一阶段避免和减少同样缺陷产生所需要采取的行动措施,并且跟踪行动执行的详细情况。
注意

缺陷分析是非常重要的一个环节,但却很容易被忽略。关于缺陷管理的更多详细内容请参考我的另一篇文章《软件缺陷的有效管理》

再来看看杯子的例子,执行一番测试之后,可能发现如下缺陷:

  1. 容积为100毫升的量杯只能盛水80毫升
  2. 杯子表面不够光滑但不影响使用
  3. 清水倒进去水变成酸的了

第一个是严重的功能缺陷,第二个属于UI问题,第三个可能是一个非常严重的安全性问题。QA需要将这些缺陷报告,并根据严重性和产品流程等来安排优先级,督促开发人员及时修复高优先级的缺陷。缺陷修复并重新测试没问题之后,要分析统计,找出产生缺陷的环节,并采取措施防止下一批杯子出现同样的问题。

5. 质量反馈和风险意识

软件产品的质量不是QA这一个角色能保证的,而是需要整个开发团队所有人员齐心协力,共同为质量负责。QA作为质量分析保证的主力军,对产品质量需要有更清晰的认识,及时识别质量风险,并反馈给整个团队。

将质量相关因素可视化出来,是反馈给团队的较为有效的方式。质量可视化包括但不限于cycle time、自动化测试覆盖率、缺陷分析报告、错误日志分析、网站分析工具统计报告、性能监控数据、安全扫描结果、用户反馈、产品环境下的缺陷统计等,可以根据项目和产品具体情况具体定义。

定期或者不定期的把这些可视化结果反馈给团队,有助于形成团队对质量的统一认识,发挥团队每个成员对于质量保证的主观能动性,从而一起制定和调整下一阶段的质量保证策略。

测试了一批杯子之后,将杯子的质量相关情况反馈给团队,内容可能是:

  • 最近这批杯子出现的缺陷明显比上一批少,可以鼓励团队再接再厉;
  • 这批杯子出现了很多严重缺陷,那么就需要组织团队一起讨论问题根源,考虑采取措施防止问题重复出现;
  • 某一批杯子等待很久才可测,需要分析原因,采取改进行动;
  • 这一批杯子生产效率明显比以前有提高,同样可以确认效率提高的原因,后续可以以此为参考持续改进和提高。

QA的必备技能要求

硬技能之扎实的计算机基础

软件测试的概念虽然已经出现多年,但QA或者软件测试工程师还是被很多人误认为就是简单的点击应用程序进行测试,是一项没有技术含量的工作。其实,从前面对QA职责的描述,大家可以看到,QA的技能要求还是蛮高的,其中非常关键的一项就是具备扎实的计算机基础,具备基本的编码能力和数据库操作能力。

只有了解系统的工作原理,才能更好的去验证系统的完备性,发现问题才能更快更有效的初步定位。因此,下次有人问你为啥选择软件测试行业,千万别说是因为自己技术不行,那样会被鄙视的。

各项软技能

从QA的职责要求可以看出,做好QA还需要多方面的软技能:

  • 快速理解业务的能力:通常丰富的领域知识和快速学习新事物的能力可以帮助快速理解业务。
  • 分析能力和定位问题的能力:执行测试和定位缺陷的过程中,这种能力非常重要。
  • 良好的沟通表达能力,包括口头和书面沟通:QA需要跟客户、需求人员、开发人员等不同角色沟通以更好的完成工作,良好的沟通将会事半功倍。
  • 踏实、认真、细心:每一个测试、每一个缺陷都需要认真的对待,容不得半点浮躁,这些技能无需细说。

当然,除此之外,能在QA职业道路上有良好的发展,极其重要的一点是对软件质量相关工作有浓厚的兴趣。

写在最后

QA在一个软件开发团队,能与需求人员一起分析需求,能与开发人员一起编写测试,能给团队和客户详细展示系统功能,还能更新整个产品/项目的质量状态,是比PM更为了解产品/项目的人,听起来就很厉害,对不对?

是的,QA就是这么神圣的工作!你心动了吗?