第26讲:基于上下文驱动思维的测试分析

从这一讲开始,我们就进入了第 5 部分内容的学习:敏捷测试分析与计划。在这一部分你将学到:测试需求分析、测试风险的识别、测试策略及测试计划的制定。今天先从基于上下文驱动的测试分析开始。

关于上下文驱动的测试思维,我在第 4 讲中简单介绍过,就是我们要关注项目的上下文(所处的环境、所要满足的条件),并认识到上下文是会变化的,测试策略和方法要根据上下文来制定,并根据其变化及时调整、不断优化。上下文驱动的测试思维是主要的敏捷思维方式之一,也是敏捷模式下测试分析的基础,需要专门讲一讲。

上下文驱动测试流派

软件测试有几个主要的流派,包括分析流派、标准流派、质量流派,敏捷测试也算一个流派,有敏捷测试的思维、敏捷测试的原则、敏捷测试的流程以及一系列敏捷测试实践,比如 UTDD、ATDD/BDD、持续测试等,另外,还有一个著名的“上下文驱动测试流派”。虽然实践它的人不是很多,如果一旦理解它,就会深受影响,对软件测试也会有崭新的理解:测试在你眼里不再是一项简单、重复的劳动,而变成了一项极具创造力的工作,并且赋予你充分的空间,以展示你的才华和技能。

上下文驱动流派最初是由 4 个人发起的,其中 Cem Kaner、James Bach 和 Bret Pettichord 在 2001 年合著了一本经典之作《软件测试经验与教训》(Lessons Learned in Software Testing)。在书里正式提出了上下文驱动流派及其 7 个原则,如图 1 所示。

James Bach 是这个流派里大名鼎鼎的代表人物,多年以来,他和 Michael Bolton 一直在实践和发展上下文驱动的思想,包括他提出的探索式测试、启发式测试策略、SBTM(Session-based Test Management)和快速软件测试(Rapid Software Testing)方法论。可以说,James Bach 的整个测试理论体系都是建立在上下文驱动的测试思维基础之上的。

上下文驱动的测试是一种思维方式,例如,它认为只有优秀实践、没有最佳实践,因为他人的最佳实践,只说明最适合他,但不一定适合我们;即使是自己的最佳实践,也只能说明昨天是最佳的,并不代表今天和明天。软件测试也一样,需要根据不同的上下文制定不同的测试方案、选择不同的测试技术和工具,并对它们运用自如,真正为你所用,然后去发现影响产品价值的缺陷。

这有点像中医看病,同样的病,针对病人的不同情况,会开出不同的药方,而且根据病情的变化,增减不同的药,调整每味药的剂量,你能说哪个药方是治疗某种病的最好药方吗?也没听说过哪位中医只要熟记药方就能成为名医。下面是一些上下文驱动测试的具体例子:

  • 在项目进行中,以前做某一重要模块的开发人员离职了,换了一个没有经验的开发人员,这一模块的风险是不是要重新评估?测试范围是不是需要调整?
  • 你的公司准备把产品的目标用户拓展到医疗或者航天领域,是不是必须遵守医疗或者航天领域的行业规范和安全标准?
  • 敏捷模式下强调测试左移,如果项目很好地实践了需求评审、设计评审和代码评审,你的测试策略是怎样的?如果没有,你的测试策略又该怎样制定?

因此,上下文驱动的测试认为不存在放之四海而皆准的最佳实践,只有根据上下文不断调整的优秀实践。也正因为如此,软件测试才是一项有创造力、需要不断磨练、提升自己的工作。这样的工作才更有意思,不是吗?

与上下文驱动的软件测试相对立的实践是标准流派,一切皆有标准可以参考,可以按部就班进行测试,按照标准所要求的方法、流程和步骤进行测试。标准不仅明确,而且稳定、很少变化,基于标准去做测试,就简单得多,几乎不需要动什么脑子,只要对照标准去做检查(check),检查产品是否符合标准的要求。所以 James 等上下文驱动流派认为这种“检查”不是测试,虽然许多人喜欢这种测试方式,操作简单、上手快、容易复制,也容易实现度量,成熟度也能一级一级地提升上去。

而上下文驱动的测试正好相反,它认为测试是不能标准化的,因为软件研发中没有任何一个上下文是相同的,不同的上下文就需要不同的测试策略和测试方法,提倡关注对于业务需求的测试覆盖和发现对用户有影响的缺陷。

同时,上下文驱动也是敏捷测试甚至是敏捷开发的重要基础。因为敏捷模式强调拥抱变化,快速响应客户需求,而实践上下文驱动的软件测试就是要根据项目的变化及时调整测试策略和测试方法,给与快速和持续的反馈。

基于上下文驱动的启发式测试策略(Heuristic Test Strategy)侧重考虑质量标准、项目背景、产品元素等 3 个方面对于测试技术、方法、工具的影响,每个方面都包含多项因素,即各种上下文因素,并最终向用户交付满足其质量要求的产品,如图 2 所示。只有把上下文各种因素的影响搞清楚,基于上下文驱动的测试思维才能落地,下面我们就来好好分析、讨论这些上下文因素。

质量要求

软件的质量要求,从根本上说是为了引导和满足用户的需求。软件测试的目标在一定意义上说,就是为了保证软件产品质量具有较高的水平。产品的质量主要靠构建,也在很大程度上依赖于软件测试的投入以及执行的结果,所以要做好测试工作,必须认真回答下面几个问题。

  • 软件给谁用?

用户是谁?有天天离不开它的核心用户,也有偶尔使用的外部用户,如系统后台维护、技术支持的用户。当前的用户构成怎样?拿到的用户画像是怎样的?年龄、职业、受教育程度等是如何分布的?未来哪些人会成为新的用户?软件测试人员要站在用户角度想问题,分析、设计软件测试。下一讲,我会专门讲解作为测试人员如何培养自己的业务与用户体验分析技能。

  • 用户对质量有什么具体要求?

根据 ISO 25000 系列标准,软件产品质量包含 8 大质量特性——功能适应性、兼容性、可靠性、易用性、安全性、效率(性能)、可维护性和可移植性,每项质量特性还进一步分为多项子特性,如图 3 所示。

基于这些属性,结合用户、业务和产品特点等进行更深入的分析,以了解对质量的具体要求,哪些质量特性需要优先关注。比如对于运营商定制的手机产品,不同的运营商有不同的验收测试体系和质量要求,美国 AT&T 制定的 10776 等系列标准,对手机稳定性的要求非常高。

  • 参照哪些质量标准或行业规范?

产品必须要遵守哪些标准或行业标准?这也是需要了解清楚的。无论是航空航天、汽车电子行业,还是金融、交通等,除了通用的国际 / 国家标准,还有特定的行业质量标准或规范。了解用户来自哪个领域或行业,就要收集和熟悉该行业的规范和标准。例如,如果项目是证券行业的应用系统,就属于金融行业,那么则有 200 多项相关规范标准。

对于产品的特定功能,也有相应的规范和认证,比如支持蓝牙功能的产品,如果想在产品外观上标明蓝牙标志,则必须通过 BQB(Bluetooth Qualification Body)认证,否则会被蓝牙技术联盟视为侵权。这时,企业需要考虑如何开展预测试,以保证产品在预期的时间内拿到认证。

项目因素

软件测试是软件项目的一部分,要做好软件测试,自然要清楚项目的背景,特别是和软件测试相关的项目要素,获取、分析和综合理解与这些要素相关的详细信息,更好的明确测试目标、测试范围、测试进度安排、测试资源、测试环境等,采用相适应的测试方法和策略,更好地开展测试活动。需要收集的项目因素包括以下几个。

  • 项目目标:测试是为了实现项目的目标,或者说,测试目标是在项目目标的基础上制定的。
  • 交付物:每次产品发布中,研发团队不仅要交付软件版本,而且要交付相关的文档,包括用户手册、管理员手册等。交付物也直接影响测试范围和测试工作,如果要交付用户手册、管理员手册等,这些文档也需要验证;如果要交付测试计划、测试用例,那么自然必须要有而且需要规范、易读。
  • 质量要求:这里的质量要求是指当前项目(即敏捷中的每次迭代)对质量的具体要求。例如,这次迭代中待实现的某个功能要求团队特别关注,而另一个功能只是尝试,这样在功能测试项的优先级安排上,前一个功能的优先级要高得多——尽早测试、充分测试;再比如,这次迭代系统能支持的用户并发数要比上次迭代提高 30%,决定了性能测试验证的具体指标值。
  • 项目范围:在敏捷开发里,每次迭代的目标是产生一个可交付的软件,但不一定每次迭代后都必须交付或发布给用户,很多团队选择几次迭代发布一次。每个要发布的版本及其中每次迭代的用户故事列表就构成了项目范围,项目范围是决定测试范围的关键要素之一。
  • 进度:项目(每次迭代)开始和结束日期、期间重要的里程碑等会影响测试计划的制定,例如每次迭代中持续测试、用户故事验收测试以及后续的端到端的验收测试,都需要参考项目进度计划来制定。
  • 可用的资源:每项测试活动都需要资源,而资源都是有限的,清楚项目的预算和资源,包括可用的人员、工具、环境等,对测试人员安排、测试环境准备都是有必要的。
  • 项目类型:是长期性的产品开发,还是一次性项目?是独立项目,还是多方合作的综合性集成项目?和合作方的合作方式是什么?是本地项目,还是外包项目?
  • 研发团队:研发团队的人员数量以及技术水平。开发、测试、业务分析的相关经验如何?单元测试是否充分?代码评审效果以往表现如何?这些对测试策略、测试工作量都有较大影响。
  • 开发工具和语言:是 Visual Studio,还是 Eclipse、IDEA、PowerBuilder?是 Java/JSP,还是 C++、Python、Go 等语言的一种或几种?开发工具和编程语言的选择对测试环境搭建、自动化测试实施等也有影响。

产品元素

产品就是我们的测试对象,自然更要关注。项目一旦启动,测试就要尽早介入,了解产品需求,了解产品的架构设计、界面设计、可用性设计、安全性设计等,并参与相关评审,通过这些活动,能够更好的掌握被测系统。

为了更好分析被测对象,可以从以下几个方面去分析。

  • 结构:软件系统的结构体现在层次性、组件化和接口标准化等。基于这些信息,从而能够考虑是否可以进行分层测试、面向接口进行测试,以及如何构建 Mock 对象等。
  • 功能:产品的业务需求是通过软件功能承载的。同时,还需要了解系统功能之间的依赖关系、功能之间的交互作用等,基于这些信息,才能更有效地开展功能测试以及功能之间的交互测试。
  • 数据:从测试覆盖来看,可以分为两部分:控制流和数据流,控制流体现在代码逻辑覆盖、基本路径覆盖和业务流程覆盖,而数据流则体现在业务数据的输入/输出、存储和恢复等方面的覆盖上,一些业务规则也是由数据构成,甚至可以说,整个计算机系统就是在处理数据,所以在许多时候,数据是测试研究的重要对象。
  • 平台:软件运行的平台,包括操作系统、数据库、浏览器、虚拟机、云平台及平台参数的组合,是测试环境设置、兼容性测试重点考虑的因素。
  • 操作:用户的行为、操作方式,包括产品是否提供遥控器操作、用户界面触摸操作?对于触屏设备,手指的触摸方式;另外,也包括异常操作、恢复出厂设置操作等。
  • 时间:在测试实时应用系统或对时间敏感的应用系统测试之时,比如在线视频系统、嵌入式系统、工业物联网等,需要特别关注。

另外,Google 还有对产品研究的一个模型:ACC,即特性、组件(结构)、能力/功能等。

  • 测试技术特性:Attributes(Adjectives of the system),区分竞争对手、提升产品质量的表现, 比如快、安全、稳定、优雅等。
  • 组件/模块:Components(Nouns of the system),系统构成的单元等,比如 Google+ 的个人信息、圈子、通知、帖子、评论、照片等。
  • 能力/功能:Capabilities(Verbs of the system),特定组件要满足系统特性所需要的能力,比如在线购物系统需要“用 HTTPS 处理交易、在购物篮里增加商品、显示库存、计算总额、按交易量排序”等。

今天的课到这里就结束了,我来总结一下:

  • 启发式测试策略是上下文驱动的测试思维的具体实践,主要从产品的质量标准、项目背景、产品元素等 3 个方面考虑对测试技术的影响,从而向用户交付满足其需求的产品;
  • 质量标准主要从 3 个方面考虑,即产品的目标用户、对质量的具体要求、参照哪些质量标准;
  • 项目背景需要考虑多个因素,包括项目目标、交付物、项目的具体质量要求等;
  • 产品元素主要从 6 个方面去分析,包括产品结构、功能、数据、平台、操作、时间等。

最后留一个思考题给你:你认为上下文驱动的思维适用于自动化测试吗?如何让工具更好的为人所用、更好的为测试服务?可以参考我公众号的几篇连载《上下文驱动的自动化测试方法》(原著是 James Bach)文章。


第27讲:如何培养自己的业务与用户体验分析技能?

上一讲我们讨论了“基于上下文驱动思维的测试分析”,因为在敏捷开发模式下,我们强调持续交付、持续测试,整个测试过程是非常动态的,所以必须关注上下文的变化,基于上下文来制定测试策略和方法。上下文驱动思维是在第 3 讲中所讨论的主要敏捷测试思维方式之一,而其中另一种主要思维方式——“用户思维”,不仅和质量因素相关,而且还会更有助于测试需求分析和用户体验分析,我们有必要在这一讲先讨论一下“用户思维”。

用户思维

之前,我们说用户思维,就是一切从用户角度出发,站在用户角度去思考产品的功能特性,扮演用户角色进行测试。在敏捷中,强调交付价值给用户,这种价值是对用户有价值,而不是对开发人员、测试人员等有价值,需要更强的用户思维。所以,在敏捷中用户思维,可以定义为:不要打造更好的产品,而要打造更好的用户,即由原来重点关注如何提升产品质量转移到如何帮助用户完成目标,取得卓越的成功。

这和思科的文化倒是非常吻合的,思科从来没有提“让客户满意”,而是帮助客户、让客户的业务获得成功。我在第 9 讲讨论“如何营造质量文化”时提到过,之前配戴过的思科(Cisco )badge,上面所有的思科文化都是为了有助于“客户成功(Customer Success)”,这就是典型的用户思维。

正如 Kathy Sierra 在《用户思维+:好产品让用户为自己尖叫》书中揭示了有点残酷的事实:用户并不关心你是谁,能做什么,他们只关心自己看起来怎么样,不会因为真的喜欢产品而说喜欢,而是因为他们自己喜欢。而某款产品之所以能够成功,也只有一个原因,那就是它成就了用户(Make Users Awesome)。

有了这样的认知,客户思维又上升了一个台阶,更关注客户的真实愿望,会主动和客户交流,聆听客户的心声,挖掘客户的真实需求。

在实际的业务需求分析中,完全站在用户的角度去看问题,从用户的喜怒哀乐出发,反过来质疑产品。我们可以扮演客户的角色,进入角色所处的整个业务操作的环境中,获取一种浸入式体验,从而更好地理解产品的应用场景或发现更多的应用场景。

场景是测试需求的灵魂

20 世纪科学界有一位奇特的通才,那就是美国经济学家、政治学家、认知科学家、1978 年诺贝尔经济学奖得主、1975 年图灵奖得主赫伯特·西蒙曾经指出,因为规律是从具体的场景中抽离并综合得到的,还原或运用时需要结合具体的、即时的场景。

测试就是对原来抽象的业务需求的一种还原,通过还原来验证需求。所以产品的应用场景是测试特别所关注的,无论是在第 24 讲 BDD 中谈到用户故事的验收标准,需要场景去覆盖,尽可能捕获各种场景覆盖验收标准,还是后续谈到探索式测试,也需要有想象力,在测试设计、执行和学习中不断发现新的场景,这样才能更好地完成敏捷测试,所以说,场景是敏捷测试需求的灵魂

有人说,“场”是时间和空间的结合。任何行为一定发生在特定的空间中的某一个瞬间,时空组合产生许多美妙的上下文,让我们在这美妙的时空中看到不同的情景,这就需要和用户有心灵的沟通,和产品有更多的交互,去发现场景。发现新的场景后,也会产生新的情绪,会促进新的想象空间,从而会发现更多的场景。这个过程,也给测试增加了不少乐趣。

有一个例子能说明这样的问题。有段时间,佳能公司为了更好的销售佳能相机,搞了一个“感动常在”的活动,去征集用佳能相机捕获到那些感人至深的一瞬间的照片,然后把这些照片放出来进行市场宣传。佳能公司,没有宣传相机,而是宣传无数个美丽或富有朝气的“你”。买相机的,其实就是你,你是用户,通过相机来塑造伟大的你。

相机再怎么漂亮,也没有价值,相机是为了塑造拥有它的用户,这就是前面说的用户思维,但仅仅有用户思维还不够,还需要让用户相信这点。为此佳能广泛地收集照片,从而发现那些感人至深的场景——比如运动、演唱、户外活动等,只有这些真实的场景才会真正感动我们。如果能感动我们,我们就很自然的去买相机。

基于场景的测试方法,目前是敏捷测试中常用的方法,包括事件流、状态树等设计方法都和场景有关,我们会在第 37 讲中再详细讨论这些方法。测试中生动的场景,不仅涉及一些不同的环境、同一种环境的不同配置和配置组合,还包括一些前置条件、后置条件、异常操作、异常数据的输入/输出等。

业务分析

从需求来看,不能简单看做是用户需求,而是要将其分为三个层次来看,具体如下。

  • 业务需求:满足各种业务目标而对业务实际运行、操作的要求,是业务分析的主要对象,也是软件系统必须满足的、最基本的要求。
  • 用户角色/干系人需求:用户/干系人都是服务于业务的,它们在业务中扮演着不同角色,发挥不同的作用,自然对软件系统有着各自特定的需求,就像前面 Epic、用户故事、场景所描述的。
  • 系统功能和非功能性需求,是为了满足上述两层需求而要求软件系统所具备的特性。

针对业务需求,我们要厘清业务角色、业务实体、业务流程、业务活动及其之间的关系,如图 3 所示。但业务涉及的内容,不局限于这些,还包括业务规则、业务操作、业务数据、业务安全性、业务可管理性和业务发展等。业务分析的核心还是业务实体关系图和业务流程图,前者更有利于搞清楚业务数据,而后者有利于搞清楚业务活动、业务角色及其之间的关系。做业务分析,一定要把业务流程图画出来,业务角色、业务活动和业务规则等也会慢慢浮现出来。业务规则需要细致的梳理,从而进一步完善业务流程(往往会增加一些业务流程的分支),业务流程图和业务规则的完善则是相互促进的过程。

针对用户需求,还可以进行下列的分析工作:

  • 用户细分,不同的用户群有不同的需求,创建细分用户群(即将具有某些共同关键特征或者共同需求的用户划分成组),从而更能揭示用户的真实需求,不同用户群的需求也有可能是彼此矛盾的,他们在使用相同功能时,需要考虑让他们选择不同的操作方式;
  • 可用性和用户研究,包括问卷调查、卡片排序法、焦点小组、任务分析、用户测试等方法/工具来获取用户信息、了解用户行为等;
  • 创建人物角色,基于上面的用户研究,从中提取出的、可成为一些典型的虚拟人物,从而更好地演绎用户使用产品的场景。

用户体验要素

基于用户思维,设身处地为用户着想,去不断挖掘用户的需求和期望、不断挖掘产品的应用场景,这些都是敏捷测试人员的基本素质。在这基础上,如何真正更好地运用用户思维,洞察业务需求及其应用场景,审视产品的各个维度,是否符合用户的需求,则需要培养对用户体验的感性认识和专业的理解。

感性认识,属于第六感觉,需要平时多观察,和用户经常沟通获得。这里更侧重讨论专业的理解。根据相关研究,影响用户体验的额外两个因素:内容、技术,内容要符合用户的实际需求和偏好等,而技术从性能、稳定性、功耗等各个方面来提供对用户体验的保障措施,确保用户能流畅地、稳定地使用产品。

更好地分析用户体验,一般认为可以进行分层研究,《用户体验要素 : 以用户为中心的产品设计》一书中介绍了五层模型。

  • 表现层:所呈现的具体细节,用户感知体验主要来源于这一层。
  • 框架层:信息设计、界面设计或空间布局,确定了在 UI 交互界面上交互元素的位置和排列方式,允许用户以不同的方式浏览,并帮助用户理解使用。
  • 结构层:确定元素之间的逻辑关系,包括系统各种特性和功能最合适的组合方式,例如用户如何到达某个页面,以及处理完之后去哪里。框架是结构的具体表达方式,而结构层则用来设计、指引用户如何到达某个特定的页面。
  • 范围层:定义软件的需求及其优先级,即特性和功能就构成了系统的范围层,创建怎样的功能规格或内容需求,具体实现哪些功能。
  • 战略层,实现产品目标,关注并考虑如何满足外部用户的业务需求,这是在设计用户体验过程中做出每一个决定的基础。产品目标:我们要通过这个产品得到什么。用户需求:我们的用户要通过这个产品得到什么。

在进行用户体验分析时,还需要从用户角度去理解 “交互组件将怎样工作”。这时需要建立人们熟悉的概念模型,并审视软件使用方式与现实经验是否一致、交互方式在整个系统中是否保持一致。为了预防错误,像银行系统,用户能输入的东西很少,大部分是选择,即将系统设计成不容易或不可能犯错那种操作方式。如果出错,系统能帮助用户找出错误并改正它们,比如提示比较恰当、显著,并能给用户提供从错误中恢复的方式。

从系统结构看,有层级结构、矩阵结构、线性结构等,关键是结构要合理,无论是自上而下还是自下而上,逻辑要清晰,让用户可以更有效地操作。

除了这些要素之外,还有一些注意事项,比如:

  • 成功的界面设计,是能让用户一眼就能发现“最重要的东西”的,如通过对比把用户的注意力吸引到重要的部分;
  • 帮助用户理解“他们在哪里”以及“他们能去哪里”、“哪条路离目标更近”,可借助图标、标签系统、排版、颜色等视觉指引;
  • 每个操作步骤都是合理的,当前步骤是否自然地延续了上一个步骤中的任务;
  • 过度设计也会导致视觉的混乱,差异要足够清晰,让用户能分辨出某个设计选择是特意要传达的,一致性能避免用户的困惑和焦虑;
  • 一个产品的标准配色方案中所使用的色彩,是为了它们在一起工作而专门挑选出来的,它们之间是互补而不冲突的;
  • 不要使用非常相似但又不完全一样的风格,也不要使用过于广泛和多样的风格,只有在你需要传达不同的信息时才使用不同的风格;
  • 遵循“使用用户语言”并且“保持一致性”的命名原则,同时避免“语义歧义或者不解”;
  • 提供的功能和内容越多,猜测就变得越不可靠,总有一部分用户会猜错的,好的产品经理会做减法。

成为用户体验专家,不是简简单单的一万个小时的练习,而是一万个小时的刻意练习,比如持续不断地和用户交流,不断获得用户的反馈,获得感性和理性的双重认知。所以,能不能成为用户体验专家,不在于我讲多少内容,而是在于你自己的刻意练习。

这一讲就讲到这里,侧重讨论了用户思维和场景挖掘的重要性,并介绍了如何进行深度的业务和用户体验的分析。

最后,给你出一个练习题:针对拉勾教育App 进行用户体验分析,它哪些方面做得好,哪些方面需要进一步的改进?为什么?


第28讲:敏捷测试风险在哪里?

测试分析的一个重要任务是识别测试风险并在测试策略中做出应对。通常情况下,不论采用什么方法和技术,测试都是不彻底的:

  • 测试是不可能穷尽的,测试不能做到业务、数据、代码路径等全方位的百分之百覆盖;
  • 测试的时间及其有限,没有足够的时间完成所需的测试,这一点在敏捷测试中尤其突出。

因此我们不能保证经过测试的、交付出去的软件版本不存在任何缺陷,这些都意味着软件测试总是有风险的,基于风险的测试策略是不可或缺的。所以,软件测试风险分析和控制非常重要。软件测试风险侧重于产品质量风险,即造成测试的深度或广度不够,从而导致遗漏缺陷。测试风险管理包括测试风险的识别、分析和控制,如图 1 所示。

相比传统的软件测试,以及我们处在 VUCA 时代,敏捷测试要面临更大的挑战,测试风险主要来自四个方面:需求不清楚、需求频繁变更、时间压力及自动化测试的有效性。

需求不清楚

在本专栏的第 4 部分,我一直在强调产品需求分析过程的重要性,也介绍了很多适合敏捷模式的工具以及优秀实践,以实现需求从产品价值、商业目标到实例化需求的落地过程,如图 2 所示。

如果你的团队这样去做或者在进行类似的优秀实践时,那么需求问题带来的测试风险自然会在很大程度上降低。但现实距离理想总是有很大的差距。

敏捷项目周期短,留给团队沟通和澄清需求的时间少,造成需求不清楚的原因跟项目的复杂程度、人员素质和经验、团队沟通和协作,以及流程都有关系。比如常见的一些问题:

  • 敏捷团队在需求沟通、协作和管理方面做得不好,整体对于业务需求的理解有偏差,包括为什么做、为谁做、做什么等,下列这些情况都属于需求不清楚,如需求不完整、需求比用户实际需要的多、需求定义有错误,团队成员理解不一致,或者优先级定义有误等;
  • 或者,负责软件测试的人员没有充分参与到需求的沟通和协作过程中,对需求不了解;
  • 还有,用户故事中没有定义清晰的验收标准。

需求不清楚造成的测试风险还是很严重的,在设计合理性和 Bug 确认方面造成困难,有很大可能会漏掉真正对客户有重大影响的缺陷,如果因为需求错误而导致产品的某些功能特性需要重新设计和实现,则测试相关的活动也要返工,进而造成巨大的浪费和对项目进度的巨大影响。

需求频繁变更

相对传统的开发模式来说,敏捷开发在应对需求变更方面有很大优势,采取迭代开发的方式,每次交付小批量的功能特性。Scrum 模式下每次迭代持续 2 ~ 4 周,在每次迭代开始之前都有机会重新澄清、变更需求,或者调整需求的优先级。但尽管如此,需求频繁变更引起的测试风险也比较常见。和需求变更相关的一些常见的风险:

  • 在开发过程中紧急增加新的用户需求,需要变更用户故事列表和优先级;
  • 线上版本发现重大缺陷需要立刻修复,由于研发团队人手不够,需要重新讨论待办事项的优先级;
  • 测试人员没有参与需求变更的讨论和沟通,测试执行相关的测试用例失败才发现原来需求更改了;
  • 开发人员在实现用户故事时,发现原来定义的用户场景不合理或者和已实现的其他功能有冲突,擅自更改了用户场景但没有通知测试人员。

需求是开发和测试的源头,需求变更自然会导致测试计划、测试设计和工作量的变化,从而给项目进度或者产品质量带来风险。

时间太紧

敏捷项目时间紧,很多人认为软件测试是敏捷开发的主要瓶颈之一。软件测试确实也有很多方面需要持续改进以适应敏捷的需求,比如通过提高测试自动化水平、测试左移等实践让测试做得更快;但是另一方面,在敏捷开发流程中考虑测试比较少,制定流程的人大多不懂测试,认为测试比较简单或者任何测试都可以用自动化的方式来完成,为什么做得那么慢?因此留给测试的时间就少之又少。

软件测试在一个迭代里既要完成用户故事的验收测试,又要编写自动化测试脚本,还要为下一次迭代的测试做准备,并且需要参加需求评审、设计评审等活动。时间紧、任务重,如果再加上人手不够、测试任务安排不合理、自动化测试程度低等因素,在测试范围和测试深度上肯定会大打折扣,从而影响软件的交付质量。

自动化测试有效性

自动化测试的有效性,和研发团队想通过自动化测试达到什么目的有关。不过在敏捷测试里,自动化测试的目的比较明确:缩短测试反馈周期,提高持续交付高质量软件的能力。自动化测试有效性方面的挑战主要包括以下几点。

  • 高度的测试自动化目前来看还比较理想,落地实施面临着很大挑战。研发团队的自动化水平普遍比较低,根据调查数据显示,只有 4% 的团队自动化测试率超过了 90%。
  • 很多团队没有遵循自动化测试金字塔进行合理的分层测试。单元测试覆盖率低,测试自动化还集中在 UI 层。自动化测试发现缺陷的能力比较弱,大部分缺陷还要靠手工测试来发现。
  • 软件测试基础设施建设比较薄弱,没有实现测试自动化和 CI/CD 环境的集成,也没有使用 Cloud 和容器技术,大量时间花费在测试环境的部署和维护上面。
  • 测试用例集缺乏维护,很多测试脚本在新的软件版本上可能已经失效了,但是没有进行及时的删除或更新,导致自动化测试不能发现有效的缺陷。
  • 自动化测试执行时间过长,提供反馈的速度比较慢。对于大型复杂的软件系统,随着新的功能特性的增加,自动化回归测试的用例集越来越庞大,执行一次全回归测试的时间也越来越长。

自动化测试水平低、发现的缺陷少,手工测试的工作量降不下来,那么测试也就快不起来。要想快,只能减少测试范围,但这样会增加质量风险。

测试风险识别 Checklist

风险识别的有效办法是建立风险项目检查表,按风险内容进行逐项检查,逐个确认。对于测试的风险,可以给出如表 1 所示的风险项目检查表。

风险防范:缓解和处理

在测试风险分析中,逐项检查,确认风险之后,要找出对策,以避免风险产生或降低风险所带来的影响。表 2 给出了敏捷测试中常见的风险,这些风险发生的可能性、对测试的影响和影响程度以及如何进行预防和控制。

测试风险的控制方法如下:

  • 根据风险发生的概率和带来的影响确定风险的优先级,然后采取措施避免哪些可以避免的风险,假如测试环境不对,可以事先列出要检查的所有条目,在测试环境设置好后,由其他人员针对所列出条目进行逐条检查。
  • 转移风险,有效风险带来的后果可能非常严重,能否通过一些方法,将它转化为其他一些不会引起严重后果的低风险,假如产品在发布前发现了某个不是很重要的新功能给原有的功能带来了一个严重的 bug,此时处理这个 bug 所带来的风险就很大,对策是去掉那个新功能,转移这种风险;
  • 有些风险不可避免,就设法降低风险,比如“程序中未发现的缺陷”这种风险总是存在,就要通过提高测试用例的覆盖率来降低这种风险;
  • 为了避免、转移或降低风险,事先要做好风险管理计划,例如,把一些环节或边界上有变化、难以控制的因素列入风险管理计划中;
  • 对风险的处理还要制定一些应急的、有效的处理方案,例如,为每个关键性技术人员培养后备人员,做好人员流动的准备;
  • 在做计划时,估算资源、时间、预算等要留有余地,不要用到 100%。

今天的课到这里就结束了,我来总结一下:

  • 测试风险管理包括测试风险的识别、分析和控制;
  • 敏捷测试的风险主要来自四个方面,即需求不清楚、需求频繁变更、时间压力,以及自动化测试的有效性;
  • 识别测试风险的有效办法是建立测试风险项目检查表,按风险内容进行逐项检查,逐个确认对于测试的风险;
  • 在测试风险分析中,逐项检查,确认风险之后,要找出对策,尽可能地避免风险产生或降低风险所带来的影响。

最后留一个思考题:你认为敏捷测试中还有哪些主要风险,如何避免、转移或降低这些风险?


第29讲:启发式测试策略与测试策略制定

上一讲我们讨论了“敏捷测试风险在哪里”,有风险就有应对措施,在这些措施中蕴含着测试策略,甚至有比较激进的说法,没有测试风险,就不需要测试策略。但实际情况是,风险总是存在的,上一讲已讨论过,而且在敏捷开发模式中测试风险更严重,所以更需要测试策略。

究竟什么是测试策略呢

有一年以上测试工作经验的人,一般都有可能会谈到测试策略,但如果让他/她解释什么是测试策略,往往解释不清楚,为此,我曾经还写过一篇文章“究竟什么是测试策略?”,以帮助测试同学理解什么是测试策略。如果按照维基百科的解释:“测试策略是软件研发过程中所有测试方法的概述,其目的是提供从组织的高层目标到实际测试活动的合理推论,以实现质量保证这方面相关的目标。” 估计看到这个,还是不能理解什么是测试策略。

而我的解释则是:软件测试策略就是在测试质量和测试效率之间的一种平衡艺术,即制定或选择更合适、更有效的测试方式、测试方法和技术等,其目的是为了以最低的时间或人力成本达到最大程度地揭示产品的质量风险、尽快完成测试(即达到特定的测试目标)等。

测试策略体现在测试方式、方法和测试过程的策划上,并基于下列这些因素的考虑做出决定:

  • 测试方式,包括手工方式与自动化方式、主动方式与被动方式、静态方式与动态方式等的选择与平衡,探索式测试或基于脚本的测试、自己团队测试还是众测、外包等平衡;
  • 测试方法,包括黑盒测试还是白盒测试方法、基于数据流还是基于控制流的方法、完全组合测试方法还是组合优化测试方法、错误猜测方法还是形式化方法等平衡;
  • 测试过程,先测什么、后测试什么,对测试阶段的不同划分等。

在第 16 讲中谈到自动化测试的金字塔模型,它其实就是我们进行自动化测试时所采用的正确的测试策略,尽可能不做 UI 层自动化测试,而应该把更多的精力投在单元测试和接口测试上,从而降低自动化测试脚本开发和维护的成本,提高测试效率。有时候,选择合适的测试方法也体现了测试策略,例如,当我们面对一个被测功能,它涉及了很多个参数,而这些参数又是相互关联的,此时需要进行组合测试

但是,如果采用完全组合,其测试用例数高达 30 万,即使采用面向接口的测试,一个用例执行时间为 0.1 秒,那么需要 3 万秒的时间,相当于 8 个多小时,这在敏捷中也是不能承受的,一般需要控制在半个小时之内就能得到测试结果的反馈。这时采用三三组合测试(如果觉得两两组合覆盖率偏低的话),将测试用例数降到 1000 以内,这时只需要 100 秒时间(不到 2 分钟)就完成了测试,效率极大地提高了(只是原来的三百分之一),但测试覆盖率也只是略微降低了一些。

启发式测试策略模型

在敏捷测试中,我们常常采用启发式测试策略模型(只是启发我们进行策略分析的工具),即在第 26 讲中讨论的基于上下文驱动的启发式测试策略模型,更强调如何更好地适应上下文的变化,而且在敏捷开发中上下文变化是正常的,不变是不存在的,这对敏捷测试提出了更大的挑战。那我们如何更好地适应上下文的变化,采取合适的测试方式、方法来完成测试任务呢?

可以学习我国古代军事名著《孙子兵法》,从中获得一些灵感,帮助我们实施上下文驱动的启发式测试策略,比如 “审时度势”、“知彼知己,百战不殆”、“能因敌变化而取胜者,谓之神”,以及“用兵之法,十则围之,五则攻之,倍则分之,敌则能战之,少则能逃之,不若则能避之”等。2012 年,我和几个同事写的《完美测试》一书,其中一章就讨论了如何在测试中应用孙子兵法 36 计,引用了其中的十六计,包括“欲擒故纵”、“趁火打劫”、“连环计”、“顺手牵羊”、“偷梁换柱”、“无中生有”、“借尸还魂”等。


启发式测试策略是根据质量标准、项目背景、产品元素来选择合适的测试技术,最终交付给用户可接受的质量。但是,启发式测试策略涉及质量标准、项目背景、产品元素等 3 个方面众多的影响因素,如图 2 所示。如果我们要全面考虑这么多的因素,再制定测试策略,则花的时间特别多,快不起来;如果不考虑这些因素,直接凭感觉拍脑袋来制定测试策略,又很不科学,无法产生很好的效果。所以,启发式测试策略虽然能够普遍使用,但是不能快速、高效地指导具体的测试工作。测试人员需要因地制宜、因势利导,才能发挥其威力,那么,如何快速、高效地制定测试策略呢?

快速、高效地制定测试策略

要想快速、高效地制定测试策略,还得需要利用思维导图,能够灵活、快速、方便地增加因素或想法(其实是节点)、调整自己的想法(如删减节点),而且可以增加标记、注释、连接等图元,标记可以突显重要的元素,注释可以提高更详细的信息,连接可以建立元素之间的关联关系。

制定测试策略的过程,一定是向自己(团队)提问的过程、自我反思、自我启发的过程,这个过程中,关键会提问。例如,快速自问:

  • 当前项目重点需要考虑哪些限制因素?
  • 哪些产品元素与当前测试任务相关呢?
  • 系统会在哪些平台上运行呢?会产生哪些不兼容的问题?
  • 针对实时性,产品有什么风险?可能会有什么缺陷?
  • 通过什么测试可以发现这类缺陷?
  • 采用什么样的测试技术,可以更快地测试它们?
  • 哪些因素的组合会产生新的风险吗?
  • ……

但是,没必要像图 2 那么复杂,一般也不能使用通用模型,必须找到适合自己的启发式测试策略模型。每个团队都处在特定的行业(如汽车电子、金融、物流等)、开发特定的产品(某产品线上),这样就决定了这个团队所面临的特定质量标准、特定行业背景、特定产品类型等,质量标准、项目背景、产品元素等某些因素是不需要考虑的,某些因素相对固定,可能只有少量因素是动态的而且在当前项目中比较特殊,是值得我们特别关注的。

例如,开发某个车载系统(属于汽车电子行业),则需要考虑 ISO 26262 标准,而且涉及典型的 V2X 网络,不仅要考虑这种网络的安全性,还要考虑实时性要求,包括时间同步等方面的验证。在测试技术上,会引入网络接口测试工具、仿真技术等。借助这些测试技术,让测试不依赖于硬件(汽车),而且测试执行速度会更快、可以覆盖更多的异常场景。

在项目上,也要特别了解本项目的进度是否特别紧?处在什么阶段?如果还是尝试阶段,那么就不会直接上线,对安全性、兼容性等质量要求会低一些。在产品元素方面,也可以了解是否分层?有哪些 API?API 文档定义是否已完成等?

这样就可以完成该项目特有的启发式测试策略模型(HTSM),如图 3 所示。

定制 HTSM 的过程是应用 HTSM 的过程,也是训练我们系统思维、创造性思维的过程,不断思考、启发、再思考的过程,快速地在深度和广度探索,及时捕获调整上下文因素、风险,产生好的想法。这种练习经常做,思维自然会更敏捷,操作起来也会更快。上一个版本定制的 HTSM 也可以直接借用,然后在上面调整,达到测试资产的复用,这样测试策略制定是不是更快些?而且是一个完善、优化的过程,形成更有价值的测试资产。

制定测试策略还有一种方法,即事先维护上面所说的测试资产之一——过去采用过的或所有已知的各项测试策略(测试方式的组合、方法的运用等),标识或说明各项测试策略的应用场景。虽然它也随着时间的推进,需要更新,删除过时的、不能发挥作用的测试方式、方法和技术等,添加新的、更有效的测试方式、方法和技术等,但是对一个团队来说,只要维护唯一的一张思维导图就可以了,相对稳定,在制定测试策略前,它基本就绪,类似图 4 所示。然后,结合另外一张思维导图——列出当前这个项目所遇到的困难和风险,针对每一项困难或风险也会标上其优先级,按照优先级,快速地逐项分析,在图 4 这张思维导图中找到相对应的测试策略,这样就能够更快完成测试策略的制定。

测试策略的制定,首先要明确测试目标,这是根本,什么时候都不要忘记初心——测试目标,包括质量要求、测试交付物;接着再分析各个测试项可能存在的风险、阻碍测试目标实现的问题,了解之前重复说的项目背景、产品元素(结构、功能、数据、平台等);然后,再根据各测试项的风险优先级,由高至低去确定合适的测试策略,包括选择合适的测试方法、技术和工具。

如果所选的测试策略之间存在冲突,以服从测试目标为宗旨,并基于风险的测试策略为敏捷测试的根本策略,即质量风险越高,其策略的优先级也越高。有效的测试策略就是为了在有限的资源下完成给定的测试任务,其中可能会舍弃某些非常低或较低优先级的测试任务(缩小了测试范围,增加了一丝测试风险)。所以,正确取舍,建立合适的测试策略,在测试目标和测试风险之间达到最佳的平衡,是测试策略制定的一条基本原则。

这一讲就讲到这里了,侧重讨论了什么是测试策略、启发式测试策略,以及如何在敏捷开发中快速、高效地制定测试策略。

最后,给你出一个思考题:原来由两个人负责“拉勾教育”App 的 Android 或 iOS 某个版本(其中一个迭代的版本),现在改为你一个人负责,开发周期不变,你会采取什么样的测试策略,降低测试风险?欢迎留言讨论。


第30讲:代码依赖性分析与精准测试

你好,我是敏捷测试专栏讲师朱少民,欢迎进入第 30 讲“代码依赖性分析与精准测试”。

在传统的开发模式中,产品上市前都会做一次完整的回归测试,在这个阶段项目会严格控制代码的改动,担心会引入重大缺陷,这种全量的回归测试的工作量就会很大,而且其中有一部分测试用例的执行是没必要的、是一种浪费,这是因为被测试的这部分没有受到影响。如果在测试过程中发现了不得不修复的缺陷,那么在代码修改后就只能凭测试人员的经验选取有限数量的测试用例来做 针对性的回归测试,选取很少的测试用例,风险比较大,而且缺少科学依据。

在敏捷开发里可没有这么长的时间留给回归测试,每一次迭代中可通过持续的自动化测试进行回归测试,即面向业务的系统级别测试。自动化测试带来的好处之一就是可以加大回归测试的频率和力度。但就像我在第 28 讲中分析敏捷测试风险时说的,敏捷测试的主要风险之一是自动化测试的有效性,包括日益庞大的自动化测试用例集维护起来比较困难、发现缺陷的能力弱、执行时间长等问题。比如一个线上的软件系统,研发团队紧急修复了一个缺陷,等着发布,却需要起码几个小时的回归测试。

那么,如何提高自动化测试的有效性,进而提高敏捷测试的效率呢?精准测试技术在这方面提供了很好的解决方案。

何谓精准测试

精准测试是一种软件测试分析技术,借助算法和工具,自动建立测试用例和软件代码之间的可视化追溯,同时分析代码依赖性,从而基于影响的代码,精准选择受影响的测试(用例),最大程度地优化要执行的测试范围。精准测试可以实现的功能包括:统计测试用例集的代码覆盖率、优化测试范围、迅速定位软件缺陷,以及分析和改进软件架构设计和代码结构等。

精准测试的基本过程(实现的原理):

  • 借助代码覆盖率分析技术,建立代码和测试用例的映射关系,为每一个测试用例和代码的方法/代码块建立对应关系;
  • 对代码进行依赖性分析,了解代码的类、方法或代码块之间的相互关联或调用关系;
  • 拿到新的软件版本,和上一个软件版本做 Code Diff,确定哪些代码被改动了;
  • 基于代码和测试用例的映射关系和代码依赖关系,就能确定受影响的测试(用例);
  • 执行受影响的测试(用例)。

首先,当某个测试用例开始执行时,被测系统被驱动运行,程序内部代码执行逻辑和测试数据就会被记录并同步进行计算和分析,然后就可以得到测试用例和代码之间的映射关系。

基于用例和代码之间的映射关系,精准测试可以自动发现还没有被测试用例覆盖的代码,提醒研发人员补充新的测试用例;当某些代码发生改动,自动筛选出需要执行的回归测试用例。这就是精准测试的含义:既不多测,也不少测;软件实现了什么,就测什么;改了哪儿,就测哪儿。

精准测试可以实现软件缺陷的迅速定位。对于黑盒测试中发现的缺陷,测试人员一般会提供基于业务的功能性描述,然后配合开发人员重现缺陷、分析定位问题,这个过程往往会花费很多时间才能定位到引入缺陷的代码。而精准测试根据测试用例和代码之间的映射关系,如果测试用例执行失败,可以追溯到可疑代码块。这种数据化的沟通方式可以有效提高缺陷定位和修复的效率,从而提高了研发团队的工作效率。

精准测试旨在提升测试效率,是对现有的黑盒测试技术的补充,在软件测试过程中加入监听、数据收集和分析,可以配合人工在设计用例、执行用例的过程中进行数据采集、计算和分析,也可以和自动化测试系统进行对接。精准测试对于缩短自动化测试时间有帮助,对手工的回归测试(虽然在敏捷中建议用自动化方式来完成)甚至探索式测试有更大帮助。

如何建立代码和用例的映射关系

精准测试的核心是建立测试用例和代码之间的映射关系,通过记录每个测试用例在执行过程中对应的程序内部的执行细节,可以追踪到方法或代码块级别。如果测试人员关注某个方法或者代码块,它也可以追溯出测试过这段代码的测试用例,如图 1 所示。

通过从测试用例到代码的正向追溯,当测试用例在执行过程中发现软件缺陷时,可以直接定位到缺陷所在的代码,包括系统测试中难复现的缺陷,因此可以帮助开发人员快速修复缺陷。

通过从代码到测试用例的反向追溯,可以进行软件不同版本之间的代码差异化分析,从而得到代码修改部分所影响的测试范围,以确定回归测试中包含的测试用例。如果新的版本中有新增的代码,则会自动提示研发人员补充新的测试用例来覆盖。

实现用例和代码的关联需要在用例执行时获取到被测应用在代码级别的方法调用链。下面就来介绍一下具体的实现技术。

代码依赖性分析

代码之间的依赖关系是比较复杂的,当执行一个测试用例时,从被测系统的代码层次来看,是调用了一系列的方法。软件代码的依赖关系包括:

  • 系统功能模块内部方法之间的直接调用、参数传递等;
  • 系统功能模块之间的接口调用,包括同步调用和异步调用等;
  • 对外部系统的调用和依赖关系;
  • 关系型数据库中数据对象之间的关联、存储过程的互相调用等,比如方法之间共用数据表。

精准测试技术通过程序插桩的方式获取方法或代码块的依赖关系,即在保证被测系统原有逻辑完整性的基础上,在程序中插入批量的探针,当测试用例驱动程序运行时,通过探针抛出程序运行的特征数据,然后对这些数据进行分析,可以获得程序的控制流和数据流信息,包括方法调用链数据。

对于 Java 应用,主流的调用链分析技术是通过 Java Agent(也叫 Java 探针)以字节码注入的方式获取程序方法级别的调用链关系,比如代码覆盖率分析工具 Jacoco。在精准测试中,你可以使用 Byte Buddy 这样的工具包,自己编写 Java Agent,也可以基于一些成熟的获取应用调用链的开源工具开发自己团队的精准测试框架,比如 Pinpoint、SkyWalking 等。

以 Pinpoint 为例,Pinpoint 用于大型分布式系统的全链路监控,可以获取不同服务之间、服务与数据库、服务内部的方法等调用关系。不需要修改服务的代码即可加载 Agent,从而实现无侵入式的调用链采集。其核心还是基于 JVM 的 Java Agent 机制,通过在被测服务的启动命令中添加 JVM 参数来指定 pinpoint agent 加载路径。如下所示:

-javaagent:/home1/irteam/apps/pinpoint-agent/current/pinpoint-bootstrap-1.8.3.jar
-Dpinpoint.applicationName=ApiGateway
-Dpinpoint.agentId=apigw01

下面是来自 pintpoint 官网的一个例子,图 2 显示了服务 API Gateway 在一次调用中服务之间的调用链,以及和数据库、第三方应用的调用关系。图 3 显示了服务内部代码级别的调用关系,可以细化到方法级别。

另外,精准测试技术可以帮助研发人员理解并优化软件架构设计。软件架构要尽量做到“高内聚、低耦合”。尽量把相关功能内聚到一个模块,减少模块之间的关联和依赖。如果代码之间的依赖度高、模块之间的耦合性强,一个方法的改动影响到的方法或功能模块就会很多,识别出的测试范围就会很大,这样就失去了精准测试的意义。

精准测试技术可以根据收集到的数据建立一个软件系统关系图并且可视化的呈现出来,包括方法之间、系统模块之间、和外部系统之间的调用关系,以及数据库。研发人员可以清楚的了解代码之间的依赖关系,并据此进行系统架构和代码结构的优化,尽量降低耦合性。

代码的变更分析

实现回归测试用例集的精准选择离不开对代码进行变更分析,就是通过新的软件版本和上一个软件版本的对比,获取新的软件版本中有哪些代码变更,然后根据差异选择测试用例或补充新的测试用例。

代码分析工具包括一些代码管理工具自带的命令对源代码进行对比,比如 SVN-diff、git-diff等。另外,IDA Pro 是一款交互式的反汇编软件,可以对软件版本的二进制文件进行差异分析,不仅比较代码本身的差异,而且还可以比较编译时引入的第三方代码库、编译参数及开关引起的差异。

测试用例集如何优化

优化黑盒测试用例集:精准测试通过代码覆盖率的统计及等价类划分功能,自动发现测试用例集中的冗余部分以及需要补充的测试用例。如果两个测试用例属于同一等价类,那么其中一个测试用例就是冗余的,可以删除。对于有大量脚本的自动化测试集,据此进行优化,从而降低对自动化用例的维护成本。

对应的精准测试过程如图 5 所示:首先执行每个自动化测试用例,通过代码依赖性分析获取测试用例和方法之间的对应关系,以及方法之间的调用关系,然后给出测试范围优化建议。同时,在此基础上建立一个知识库,为回归测试范围的优化提供基础。知识库包括两部分内容:测试用例和方法之间的映射关系,方法之间的调用关系

自动筛选回归测试用例集:通过代码变更分析以及用来存储用例和代码映射关系的知识库,就可以为新提交的软件版本智能的筛选回归测试用例。

首先分析新的软件版本有哪些变更,根据已经建立的知识库,计算出改动的代码影响到哪些功能,需要执行哪些测试用例,这样就可以减少针对每个版本的自动化测试用例集,缩短自动化测试的运行时间,过程如图 6 所示。

不少公司的研发团队根据精准测试的技术理论开发了自己的技术框架,实现了测试用例和代码的可视化的双向追溯、回归测试用例集的自动筛选甚至是智能选取、代码覆盖率分析、缺陷定位,以及测试用例聚类分析、与自动化测试平台的集成等功能。

今天这一讲到这里就结束了,总结一下这一讲的重点。
精准测试是一种新的软件测试分析技术,借助算法和工具,自动建立测试用例和软件代码之间的可视化追溯,实现测试范围的优化和缺陷的迅速定位。
用例和代码之间的映射关系是精准测试的技术核心。从用例到代码的正向追溯可以迅速定位缺陷并帮助改进软件架构设计和代码结构;从代码到用例的反向追溯可以帮助优化测试范围、自动筛选回归测试用例。
代码依赖性分析是实现用例和代码之间关联的基础。

最后留一个思考题给你:测试技术的选择是上下文驱动的,你认为精准测试技术适合你所在的团队及正在开发的产品/项目吗?理由是什么?


第31讲:敏捷测试要不要计划?

凡事预则立,不预则废”,没有事先的计划和准备,就不能获得项目的胜利,这充分体现了计划的重要性,没有计划是万万不可的,即使是在敏捷开发模式下,虽然在敏捷宣言中有这样一句“拥抱变化 胜于 遵循计划”。但是,敏捷宣言末尾有一行小字,特别提醒我们右边项也是有价值的,即“遵循计划”是有价值的,只是“拥抱变化”更具有价值。

一方面我们需要写一个简洁的测试计划书,指导后续的测试工作;另一方面计划也是一个过程,正如我们常说的,计划不是一个阶段性的活动,不只是为了写一个计划书,而是贯穿整个研发项目周期的计划过程,所以计划要用“Planning”,强调是一个基于上下文的、不断优化的计划过程。

测试计划的价值

在敏捷开发中,开发节奏很快,越快的时候越要有计划,否则会更糟糕,“欲速则不达”。在制定计划过程中,让我们系统审视项目可能遇到的问题、尽早地识别出潜在的风险,能够未雨绸缪、防患于未然,对成功完成测试是很有帮助的。

制定测试计划时,首先迫使我们明确测试目标,这个目标不只是测试人员自己确定的测试目标,而是整个团队共同确定的测试目标。明确正确的测试目标自然很重要,后续所有的测试活动不就是为了达成测试目标吗?也就是目标引导我们后续如何开展测试活动,而没有目标的测试是多么的可怕。计划往往是评价实施的依据,基于测试计划,可以更好地评价测试做得如何。

事先制定测试计划,也能帮助我们界定项目的测试范围,即事先知道哪些要测,哪些可以不测,这是测试估算、资源安排的基础,也是后续测试分析、设计和执行的基础。从这个角度看制定测试计划也是必要的。

在制定一个计划时,也能帮我们厘清测试的思路,制定一个切实可行的测试方案,即解决如何测试的问题,逼着我们思考,反思过去做得不够好的地方,如何在当前项目上进行改进。简洁的测试计划还可以提供历史测试信息和可追溯性,从而推动测试的改进

如果团队、项目干系人和我们一起评审计划,并一致认可这个测试计划,也就说明计划中所定义的测试范围、所需的资源、所安排的进度等被团队接受,计划就成为项目干系人之间的一种约定,为后续的具体实施、协作提供了有力的保障

一页纸的测试计划

测试计划有价值,但我们更重要的工作还是测试的分析与设计,例如如何通过分析找出更多的场景,然后设计测试用例或脚本覆盖它们。而且,我们一直强调上下文的变化,我们会根据上下文来调整测试计划。所以,在敏捷中测试计划要尽可能写的简单,用“一页纸”来体现敏捷测试计划的简单性。虽然你可以写两页纸、三页纸的计划,不一定只写一页纸的计划,但是你能写一页纸的计划就不要写两页,你能写两页纸的计划就不要写三页,只写下那些有价值的内容,没有价值的内容就不用写。

那我们想想,哪些内容是测试计划一定要明确的?

首先,可以省去一些通用的做法、一些惯例。例如,每次写当前迭代的测试计划时,会从上一个迭代的计划书中复制过来,粘贴到这个计划中,这是在传统软件测试计划编写过程中做的事情,在敏捷测试中就不要做了。有些惯例,比如环境的例行检查、通常的入口/出口准则、上线前要做的例行检查等,都可以把它转化为一些清单(CheckList,检查表)。我们在迭代测试计划中,只记录那些本次迭代特有的内容。

其次,在敏捷测试计划中,还有哪些项是可以省略掉的?在传统测试计划中,工作量的估算是基础,特别是项目越大、团队规模就越大,这时会更关注工作量的估算,从而决定需要多少人力;而在敏捷测试中,一方面团队很小、相对稳定,另方面在做发布计划时会有估算,以决定这个需求(如用户故事)是否可以放入当前的迭代中,一旦需求放进迭代中,整个团队就要努力把它做完。即使遇到一些估算不够准确或其他困难,此时迭代周期也不会调整,而是依赖于团队的协作和努力,例如,在前期测试人员可以帮助开发做一些事情,在后期开发可以帮助测试做一些事情。分工不要那么明确,更强调团队的协作和力量,这时,估算不那么重要。在传统测试计划中,进度安排也是很重要的一项,但敏捷中完全有可能省去,因为我们更强调持续测试,在一个迭代中,没有明显的里程碑,即使有,也已成为惯例,因为迭代周期是相对固定、有节奏的。例如,前两天要完成测试需求分析和测试计划、最后一天要完成一个全回归……等已成为惯例,甚至成为流程的一部分,团队遵守就好了,没必要在每个迭代的计划中重复写。

这样讨论下来,在敏捷测试计划中,必须写下来的一些主要事项有以下 10 个。

  • 测试目标:在业务上如何更好地确保已有业务不受影响,以及易用性、性能、安全性、测试覆盖率、测试效率等方面的具体、明确的目标。
  • 交付内容:交付哪些有价值的内容给客户?交付哪些功能特性?交付哪些文档、或工作件(如测试计划、自动化脚本等)?可以包括整体的验收标准。
  • 测试项:我们将测什么、不测什么?明确要测试的功能、性能、安全性等具体测试任务,以及要做哪些合规性检查、需要测试哪些环境/平台等。
  • 人员安排:每一个测试任务都有对应的团队成员负责。
  • 假定:有没有一些假定条件?例如,这次待发布的版本只限于特定的用户使用。
  • 依赖性:前端发布依赖于后端某个版本的发布,组件之间的依赖性等。
  • 测试风险:可能会出什么样的质量问题、可能面对的测试挑战、可能无法覆盖的某些测试点等,涉及人员、测试范围、环境、时间或资源限制等不确定的因素、或潜在的负面影响。
  • 测试策略:会采用什么测试策略?采用哪些测试方法或工具?
  • 测试环境:会做哪些改变或需要进行哪些新的配置?
  • 其他:例如参考哪些文档资料?

如何编写一页纸的测试计划

在前面的几讲中,我们已经讨论了代码依赖性分析、基于上下文驱动思维的测试分析、基于用户思维的场景挖掘、测试风险识别与分析、测试策略制定,这些工作做好了,测试计划就水到渠成了,剩下的问题就是如何描述这个测试计划。

之前,我们喜欢用 Word 方式来编写测试计划,但在敏捷测试中,是时候换一种方式来表达了,即如何简洁地呈现出测试计划,团队也方便浏览,只要花上几十分钟甚至几分钟就能看完;如果有问题,也相对容易发现,对于这样的要求,团队自然会想到 WiKi、仪表板、思维导图等方式来表达。

1.WiKi 方式

为测试计划创建一个页面,就如同今天的墨客文档、腾讯在线文档,可以引用一个合适的模板(如表格方式的模板),团队成员就可以在相应的地方进行添加、修改等编辑工作,这种方式特别适合团队协作。也可以让之前所设置的测试责任人(Test Owner,TO)角色先完成一个测试计划的初稿,然后再开一个(在线)会议,团队一起快速浏览、评审这个计划,不同团队成员也可以直接在这文档上输入自己的建议或进行修改,最后再由 TO 定稿,并持续维护这个文档。

2.仪表板格式

采用仪表板(Dashboard)方式,可以使团队以一种更好的视觉方式、一目了然地查看测试计划,甚至可以加上一些色彩,突出一些重点,将团队成员的视线吸引到某个特定的区域,如测试风险、测试策略等区域,如图 1 所示。

3.思维导图方式

创建敏捷测试计划的最好方式,还是思维导图方式,它可以和之前的测试需求分析、风险分析等工作很好地衔接起来。像整理测试项、测试风险等,都是一个先发散、后收敛的过程,可以先头脑风暴,甚至不管对错,先增加内容,然后再删去不合理的内容,增加节点、删除节点这是经常发生的事,而且敏捷测试计划是一个相对变化比较频繁的动态过程、不断完善的迭代过程。

思维导图采用了一种直观的视觉方式,可以增强创造性思维和记忆力,也能体现测试计划编写的思维方式,真正能做到一页纸的测试计划——就是一张图,如图 2 所示。

针对测试项、测试风险、测试策略等,可以在思维导图上标注优先级。如果团队成员,不确定某些内容是否可以删除,也可以加注释。针对某个测试风险、测试项、场景的讨论过程中,产生的一些好的想法,也可以及时加注释。有些风险和策略有关系、有些测试项之间有依赖关系,还可以标上这种关系。

采用思维导图来制定测试计划,不再需要花一整天或好几天来写测试计划,用 2~3 个小时就能完成,团队也更乐意积极参加这种讨论,不仅效率高,而且有趣、互动性强,可以灵活展开、折叠,哪怕在手机上也可以方便浏览,随时添加测试项、删除测试项,随时调整和完善测试计划。也可以贴在墙上、白板上,使测试计划更可见,在每日站会上,结合敏捷测试计划,来审查项目的实际进展。

这一切,采用思维导图来建立和维护测试计划都是很好的,我甚至发现有些公司已经开发了企业内部的思维导图在线网站,同样可以像 WiKi 那样协作完成测试计划,只是现在不是文字,是一张丰富多彩的图。

要写出有效的测试计划,团队需要约定一些测试计划制定的原则,比如:

  • 测试计划必须给出对所交付给客户价值的衡量方法或验证方法;
  • 测试目标必须明确,符合 SMART 原则等;
  • 测试项必须列出应用场景,标注优先级;
  • 测试风险不要多,只要列出 Top 5 的测试风险;
  • 测试策略能够消除或缓解测试风险,并确保测试目标的实现;
  • 依赖性、假定等也不可或缺。

这一讲的内容就到这里了,最后给你出一个思考题:敏捷特别关注价值的交付,上面第一条原则也是“测试计划必须给出对所交付给客户价值的衡量方法或验证方法” ,那么在文中图 1 或图 2 中哪一项能反映这点?是否有改进的空间,更好地给出对所交付给客户价值的衡量方法?欢迎留言讨论。


第32讲:探索式测试与基于脚本的测试

上一讲谈到了如何完成“测试计划”相关的内容,对于第五模块“敏捷测试分析与计划”,是否意味着可以告一段落了?按照正常逻辑,这一模块可以结束了,但是考虑到探索式测试的应用,增加了三讲内容。你可能会问,探索式测试是指“设计、执行和学习同时进行”这种测试方式,只影响测试的设计和执行,与计划没有什么关系,计划该这么做还是这么做,为何要在这个模块来讨论探索式测试呢?

没错,探索式测试是指“设计、执行和学习同时进行” 这种测试方式,但要比较彻底地推行探索式测试的实施,或者说,在敏捷测试中可以采用纯粹的探索式测试,就需要引入 SBTM(Session-Based Test Management),这个会涉及到测试计划,把测试目标分解、Session 分解都可以归为测试计划的一部分,可以看作是原来测试计划的延续,所以把 SBTM 这部分内容放在了第五模块中讲解。

为了能讲解 SBTM,先做一个铺垫,必须先交代清楚“什么是探索式测试”?为什么会引入探索式测试?它和基于脚本的测试有何区别?

什么是探索式测试

探索式测试(Exploratory Test,ET)的萌芽可以追溯到 1984 年 Cem Kaner 写“Testing Computer Software”一书中所呈现的,比较明确的定义是 James Bach 1995 年给出的 “测试设计、执行、学习同时进行” ,这里的设计,应该是指测试用例的设计(测试的详细设计)。之后,距 1984 的 23 年之后(2007 年),Cem Kaner 在和众多的上下文驱动测试流派的测试人士(包括 James Bach)讨论之后,给出了比较全面的 ET 定义:

探索式测试是一种软件测试风格(Style),它强调独立测试人员(Individual Tester)的个人自由和职责(Personal Freedom and Responsibility),为了持续优化其工作的价值(Value),将测试相关学习(Test-related Learning)、测试设计(test Design)、测试执行(execution)和测试结果分析(analysis)作为相互支持的活动,在整个项目过程中并行执行。

从这个探索式测试的完整定义看,有以下几个要点:

  • 探索式测试不是测试方法、测试技术,而是一种软件测试方式(最好不要写成“探索性测试”),各种测试方法、技术依旧可以应用于这种 ET 方式中;
  • 以人为本,强调测试人员的价值,给他们更大的自由发挥空间;
  • 持续测试,设计、执行、学习和结果分析同时进行,没有明确的阶段;
  • 持续优化测试工作的价值,精益求精、追求卓越;
  • 它不只是一种辅助的测试方式,可以贯穿整个项目生命周期。

其中以人为本、持续测试和持续优化,与敏捷的价值观和原则是相同的,敏捷开发和探索式测试更加吻合,所以多年前我做了一个演讲,主题是“敏捷开发紧紧拥抱探索式测试”。

探索式测试执行可以用一个循环来表示,如图 1 所示,这个循环只是完成一个测试(用例),从测试设计、执行、分析到学习,再重新设计、执行、分析、学习……这样持续循环下去,可以看作是螺旋式不断上升的过程。

所以,这个循环有以下 4 个要点:

  • 在头脑中设计,过去我们设计测试用例是要写下来,估计一个用例要用掉几分钟或更长的时间,而这里只是在头脑中设计,一般只要几秒钟,效率会高很多;
  • 执行更流畅,过去想到一个测试用例就写下来,思路是断断续续的,现在思路是连贯的,思维更敏捷;
  • 上下文及其测试结果分析,也就是说,下一次测试是要根据上一次测试的结果来决定是否要做出调整,如果测试的结果没有达到测试人员的期望,比如没有发现 Bug,这时就需要分析,判断测试思路可能错在哪里,如何进行调整或改进,从而在头脑中重新设计测试用例,进行下一个循环;
  • 从执行/分析中学习,快速改进,一个循环只有几分钟,在这么短的时间内很可能有学习的机会,获得改进,持续下去,一年下来改进是很大的。算一算 1.01365 是多少,而这里远远超过 365 次改进的机会。

探索式测试是上下文驱动流派的具体实践与体现,强调软件研发过程中上下文(需求、进度、人员、风险...)是不断变化的,只有测试人员才能及时适应这种变化,对测试范围、思路和方法、软件的操作等做出调整,不断优化测试,尽快、尽早、尽可能多的发现软件缺陷,提高测试的有效性和效率。

基于脚本的测试

与探索式测试对立的是基于脚本的测试(Scripted Testing,ST),基于脚本的测试是指先完成测试脚本,再执行测试脚本,阶段性明确,前面一段时间专注测试脚本的设计与开发,后面一段时间专注测试脚本的执行。这里的测试脚本,包括手工执行的测试用例和工具执行的自动化测试脚本。

基于脚本的测试和传统开发的瀑布模型的思维方式是一致的,和瀑布模型的具体实施过程也是匹配的。在瀑布模型中,阶段性也是非常明确的,从需求分析、设计到实施,一个阶段一个阶段的往前推进,测试自然也是先分析、再设计,最后执行。在传统开发中,这样做有其可行性,而且也不得不这样做,这是因为:

  • 可行性,在传统开发中,需求文档、设计文档规范、详细,基于这样的需求文档、设计文档,能够清楚地理解需求和设计的实现,能够开展测试用例的设计工作;
  • 另一方面,在传统开发测试中,有一个“开发提交测试”的里程碑,即存在一个测试阶段,一旦开发将构建的版本提交给测试,即意味着测试执行阶段开始,而在这里程碑到来之前,开发没有交付版本,测试无法执行测试,只能进行测试的设计。

这也进一步证明了,有什么开发就有什么测试,如图 2 所示。

ET 与 ST 的比较

为了让你更好的理解探索式测试(ET),我们可以将它和基于脚本的测试(ST)进行比较。首先,ST 和 ET 之间也是有关系的,当 ST 中的脚本颗粒度越来越粗的时候,ST 正逼近 ET,同时 ET 也不同于 ad-hoc 测试,不是随机测试,它是有角色扮演、有场景的设计,即在进行 ET 之前,也是有准备的,甚至说有大颗粒度的设计,如图 3 所示。

正如前面所说,ST 和传统的研发模式很吻合,阶段性明确,来自于软件测试的分析流派和标准流派,注重文档及其规范性,依赖测试用例的评审来保证测试用例的质量,有利于管理和测试资产的复用,整个方式相对严谨和规范。而 ET 则是软件测试上下文驱动流派的代表,注重发挥测试人员的个人能力,特别是在缺乏明确的测试结果判断准则(而是启发式的 Test Oracle)的情况下,ET 更能发挥作用。而且,ET 直接针对被测产品进行测试,关注和产品的交互,不断质疑产品,从中也获得测试的乐趣。

测试人员直接针对产品进行测试,开发怎么改、测试就怎么测,更何况探索式测试不需要写测试用例,不需要去维护测试用例,轻装上阵,所以 ET 是最能适应产品变化的,拥抱变化。其次,ET 关注产品,直接和产品进行交互,这和敏捷宣言中核心的第 2 句“可工作的产品 胜于 详尽的文档”价值观也是吻合的,这两点进一步说明敏捷开发拥抱 ET。

测试人员和产品交互的过程不是普通的对话过程,而是运用批判性思维不断质疑产品的过程,不断把问题抛给被测系统,并观察被测系统如何反应或做出什么响应。 这样,我们可以给“软件测试”重新下一个定义,即软件测试就是测试人员不断质疑被测系统的对话过程,如图 5 所示。这时,如果将测试人员比喻为客户端,而被测系统是服务器,测试的过程就是在客户端和服务器之间建立一个 session 的过程,这样可以帮助你理解下一讲中介绍的 SBTM 中的 session。

为了更好的应对需求变化、适应快速迭代的节奏、提高测试效率,以及当测试的判断准则不够明确时,如需求文档不清晰,这时就需要引入探索式测试,而且敏捷测试和探索式测试是息息相通的,主要体现在以下几个方面:

  • 价值驱动或业务驱动,都强调做对客户有价值的事情;
  • 持续学习和改进,上下文驱动,不断学习、不断改进、精益求精;
  • 以人为本,都强调人是最重要的,要发挥每一个研发人员的潜力;
  • 效率优先,更侧重效率,强调快速完成任务,持续工作、持续交付;
  • 拥抱变化,更具有适应性,能够快速响应变化,认可“拥抱变化 胜于 遵循计划”这样的价值观;
  • 关注产品本身,认可“可工作的产品 胜于 详尽的文档”这样的价值观。

学完下一讲,你还能体会到 ET 也会实践“任务分解、时间分解”,强调面对面、更多的沟通,和敏捷有更多的相通之处,从而再一次深深体会到了 ET 更适合敏捷开发环境。

这一讲就讲到这里了,侧重讨论了什么是探索式测试、基于脚本的测试,以及它们之间有何关系、有何区别,并详细讨论了探索式测试和敏捷开发模式有许多相通之处,让你感受到敏捷开发模式会拥抱探索式测试。

最后,给你出一个思考题:上面说,探索式测试不需要设计和维护测试用例,轻装上阵,开发怎么改、测试就怎么测,所以 ET 是最能适应产品变化的,拥抱变化。这其中有没有包含某种假定、忽视了某种场景?在某种场景下,上述结论是不成立的,为什么?欢迎留言讨论。

下一讲,我将带你学习“如何采用 SBTM:从 Mission 到 Session?”,到时注意收听。


高效的敏捷测试第十一课 敏捷测试分析、策略和方法相关推荐

  1. 高效的敏捷测试第一课 敏捷测试介绍,与传统测试对比

    开篇词:重剑无锋.大道至简 你好,我是朱少民,欢迎来到我的"敏捷测试"专栏.2000 年至今,我已在测试行业摸爬滚打 20 年,因为热衷分享应该有不少同行认识我.可能是因为读过我写 ...

  2. 高效的敏捷测试第十课 BDD实践和深化

    第24讲:BDD 及其自动化实践 在第 20 讲,我介绍了 TDD.UTDD 和 ATDD,主要讨论了需求的可测试性,通过测试先行的敏捷开发理念,比如先建立用户故事的验收标准,来提升需求的质量.今天在 ...

  3. 高效的敏捷测试第四课 测试的团队协作

    第08讲:借助 Tet Owner 角色,完成团队转型? 三年前的一天,我碰到了一个之前在思科的老同事,问了下他现在软件开发采用的是什么模式? 他回答:"已全面实施敏捷开发模式了,有些团队都 ...

  4. 专访|HPE测试中心总监徐盛:测试新思维-DevOps,持续测试,更敏捷,更快速

    2016年7月22日,「HPE&msup软件技术开放日」将在上海浦东新区,张江高科技园区纳贤路799号科荣大厦小楼2楼举办,msup携手HPE揭秘全球测试中心背后的12条技术实践. 徐盛:HP ...

  5. 复制:高效程序员的45个习惯敏捷开发修炼之道 读书笔记

    为什么80%的码农都做不了架构师?>>>    第一章 敏捷-高效软件开发之道 什么是敏捷开发方法? 从语法简单到c语言,从面向过程到面向对象语言到语言标准的建立,再到设计模式,以及 ...

  6. 读书笔记 -《高效程序员的45个习惯-敏捷开发修炼之道》

    <高效程序员的45个习惯-敏捷开发修炼之道> 一本2010年出版的书,当时敏捷还只是在国外开始流行,像我这种菜鸟级根本听都没听过.这次通读了这本书,受益良多,回顾自己的职业生涯,多是漫无目 ...

  7. 深聊测开领域之:一文搞懂什么是敏捷测试,如何做敏捷测试,建议先收藏再学习。

    敏捷测试 1.引言 2.解析敏捷测试 2.1 含义 2.2 特点 2.3 为什么要进行敏捷测试 2.4 敏捷测试与传统测试对比 2.5 如何迁移敏捷测试 2.6 敏捷测试成功因素 3.总结 1.引言 ...

  8. 读书笔记之《高效程序员的45个习惯----敏捷开发之道》 摘录

    读书笔记之<高效程序员的45个习惯----敏捷开发之道>摘录 此次原创的意思是指这个文章中的内容是由笔者从<高效程序员的45个习惯----敏捷开发之道>书中摘录,而不是别人摘录 ...

  9. 《高效程序员的45个习惯——敏捷开发修炼之道》读书笔记

    <高效程序员的45个习惯--敏捷开发修炼之道>的读书笔记 <高效程序员的45个习惯--敏捷开发修炼之道>[美]Venkat Subramaniam / Andy Hunt 著 ...

最新文章

  1. 代码实战 | 用LeGO-LOAM实现BFS点云聚类和噪点剔除
  2. ThreadPoolExecutor 的八种拒绝策略 | 含番外!
  3. Powershell快速入门(二) Shell编程
  4. 【django】配置数据库(mysql)
  5. 为啥用redis解决会话呢?
  6. 浏览器打开出现证书错误_2分钟轻松解决ie证书错误
  7. [VirtaulBox]网络连接设置
  8. java 字符串原样输出_Java 中如何原样输出转义符号
  9. 如何自己用U盘重装系统
  10. mysql删除注册表mysqld要删除吗_原神官方删除魈的观测枢数据,又要拆分机制吗?策划应该不傻吧?...
  11. 0基础学python要多久-零基础python培训需要学多久?
  12. 千兆以太网(二)——MDIO接口协议
  13. oracle修改主机名造成启动错误
  14. iOS音频采集技术解读:如何实现男女变声的音效?
  15. [深度学习 - 实战项目] yoloV5人脸侦测arcFace人脸识别silentFace静态活体检测
  16. B2B企业越早做网络营销会有哪些优势 由上海添力张进老师讲解
  17. Kubernetes详解
  18. 迦瓦栈队 团队第六周项目总结
  19. Direct2D编程入门
  20. quectel(调用相关命令)7

热门文章

  1. 朋友圈可以定时发送吗?
  2. Java序列化的几种方式以及序列化的作用(文章有所改变)
  3. 关于手机号码合法性判断
  4. 长图预警,全网最全的23个免费无背景PNG素材网站汇总,让你有用不完的资源!!
  5. vue中slot插口的用法
  6. 造车,富士康是认真的?
  7. 忘记电脑密码 ,修改开机密码
  8. 虹科方案 | 虹科Vdoo安全平台:CVE-2020-25860 - 在 RAUC 嵌入式固件更新框架中发现的重大漏洞
  9. c#编写病毒专杀工具(一)
  10. 万达保安“苦修Java”,7个月破茧成蝶,如今薪资翻了4倍