基础

本章解释了软件测试的基本概念,这些概念将在后面的章节中得到应用。介绍了软件测试的七个基本原则,本章的大部分内容都是用来解释测试过程的细节和它所涉及的各种活动。最后,我们将讨论测试中涉及的心理问题,以及如何避免或解决这些问题。

2.1概念和动机

  • 质量要求

工业生产的产品通常会被抽查,以确保它们满足计划的要求并执行所需的任务。不同的产品有不同的质量要求,如果最终产品有缺陷或瑕疵,就必须修改生产过程或设计来补救。

  • 软件是无形的

检查产品的一部分或成品是很棘手的,因为产品本身实际上并不是有形的,这使得 "亲手 "测试不可能。目测检查是有限的,只能通过对开发文件的仔细检查来进行。

  • 有问题的软件很严重

不可靠的软件或根本不能执行所需的任务的软件会产生很大的问题。糟糕的软件会花费时间和金钱,并会毁掉声誉。它甚至可以危及人的生命--例如,当部分自主车辆中的 "自动驾驶 "软件做出错误的反应或反应过晚。

  • 测试有助于评估软件质量

因此,检查软件产品的质量,以尽量减少故障或崩溃的风险是极其重要的。测试可以监控软件质量,并通过在开发阶段揭示故障来降低风险。因此,软件测试是一项重要的但也是非常复杂的任务。

VSR-II系统的每个版本在交付和推出之前都必须进行适当的测试。这样做的目的是为了在故障造成任何损害之前识别和补救故障。例如,如果系统以错误的方式执行订单,会给客户、经销商和制造商带来严重的财务问题,同时也会损害制造商的形象。像这样未被发现的故障会增加软件运行中的风险。

  • 测试采取抽查的方式

测试对象被输入涵盖各种测试案例的测试数据,然后被执行。接下来的评估是检查测试对象是否满足其计划的要求。

  • 测试不仅仅是在计算机上执行测试

测试所涉及的不仅仅是执行一系列的测试用例。测试过程涉及一系列独立的活动,而执行测试和检查结果只是其中的两项。其他测试活动包括测试计划,测试分析,以及测试用例的设计和实施。其他活动包括撰写测试进度和结果的报告,以及风险分析。根据产品生命周期的不同阶段,测试活动的组织方式也不同。测试活动和文件通常在客户和供应商之间有合同规定,或基于公司自己的内部准则。在第2.3节和第6.3节中,对软件测试中涉及的各个活动进行了详细描述。

  • 静态和动态测试

除了在计算机上进行的动态测试(见第5章),需求规格、usercase和源代码等文件也需要在开发过程中尽早测试。这些被称为静态测试(见第4章)。文档中的错误越早被发现和补救,对未来的开发过程就越有利,因为你将不再使用有缺陷的源材料。

  • 验证和确认(Verification and validation)

测试不仅仅是检查系统是否满足其需求、用户故事或其他规范;它也是为了确保产品在真实世界的环境中满足用户的愿望和期望。换句话说,就是检查是否可以按照预期使用该系统,并确保它实现了计划中的目的。因此,测试也包括验证。

  • 没有一个大型系统是没有错误的

目前,不存在无故障的软件系统,对于超过一定复杂程度的系统或有大量代码的系统,这种情况不太可能改变。许多故障是由于在代码开发过程中未能识别或测试异常情况造成的--比如未能考虑到闰年,或者在时间或资源分配方面没有考虑到限制。

  • 通过测试无法避免故障的发生

除了非常小的程序之外,即使你进行的每一次测试的结果都是零缺陷,你也不能保证额外的测试不会发现以前没有发现的故障。通过测试来证明完全没有缺陷是不可能的。

2.1.1缺陷和故障术语

  • 作为测试起点的测试基础

只有当你事先定义了在这种情况下到底应该发生什么时,才能将这种情况归类为故障。为了做出这样的定义,你需要知道你所测试的(子)系统的需求以及其他附加信息。在这种情况下,我们谈论的是测试的基础,它是决定特定功能是否有问题的基础。

  • 什么算作是缺陷(defect)?

缺陷被定义为未能满足预定的要求,或实际行为(在运行时或测试时)与预期行为(如规范、需求或用户故事中定义的)之间的差异。换句话说,什么时候系统的行为不符合其实际需求?

与物理系统不同,软件系统不会因为年龄或磨损而失效。的缺陷从软件编码的那一刻起就存在,但只有在系统运行时才会显现出来。

  • 故障(Faults)导致失败

系统故障是由故障引起的,只有在测试期间或运行时才会被测试人员或用户发现。例如,当系统产生错误的输出或崩溃时,我们需要区分故障的影响和它的原因。系统故障是由软件中的故障引起的,由此产生的状况被认为是一种缺陷。"bug"一词也被用来描述由编码错误导致的缺陷,如代码中错误的编程或遗忘的指令。

  • 缺陷掩盖

故障有可能被程序中其他部分的其他故障所掩盖。在这种情况下,有问题的故障只有在其他故障被纠正后才会变得明显。
并非所有的故障都会导致系统失败,有些失败对所有的用户来说从未发生过,或发生过一次,或不断发生。

  • 人会出错:错误的发生有各种原因。一些典型的(根本)原因是:
    • 所有的人都会犯错!
    • 时间压力在软件项目中经常出现,是错误的经常性来源。
    • 手头的任务、系统结构、系统设计或源代码的复杂性。
    • 项目参与者之间的误解--通常表现为对需求或其他文件的不同解释。
    • 对内部和外部接口的系统交互有关的误解。大型系统通常有大量的接口。
    • 技术的复杂性,或在项目中引入的项目参与者以前不知道的新技术。
    • 项目参与者没有足够的经验或没有适当的培训。

人为错误导致部分代码出现故障,然后导致某种可见的系统故障,理想情况下,这种故障在测试中被发现。静态测试可以直接检测源代码中的故障。

系统故障也可以由环境问题引起,如辐射和磁性,或由物理污染引起的硬件和固件故障。我们在这里将不讨论这些类型的故障。

  • 假阳性和假阴性结果

并非每个意外的测试结果都等同于失败。通常情况下,即使潜在的故障(或其原因)不是测试对象的一部分,测试也会显示失败。这样的结果被称为 "假阳性"。也可能出现相反的结果--即测试应该揭示故障的存在,但故障并没有发生。这种类型的结果被称为 "假阴性"。在评估你的测试结果时,你必须牢记这两种情况。你的结果也可以是 "正确的阳性"(通过测试发现故障)或 "正确的阴性"(通过测试确认预期行为)。关于这些情况的更多细节,见第6.4.1节。

  • 从错误中学习

如果通过测试发现了故障和导致故障的错误或失误,那么值得仔细研究一下原因,以便学习如何避免在将来犯同样(或类似)的错误或失误。你通过这种方式获得的知识可以帮助你优化你的流程,减少或防止更多故障的发生。

案例研究: 模糊的需求是导致软件故障的原因之一

客户可以使用VSR EasyFinance模块来计算各种车辆融资方案。系统使用的利率存储在一个表中,尽管购买涉及促销和特别优惠的车辆可能会有不同的利率。
VSR-II要包括以下的额外要求:
REQ:如果客户同意并通过在线信用检查,EasyFinance模块会从一个特殊的奖励利率表中应用一个利率。
不幸的是,这项要求的作者忘记澄清,对于作为特别优惠的一部分出售的车辆,不允许降低利率。这导致这种特殊情况在第一个版本中没有被测试。反过来,这意味着客户在网上得到了低利率,但在开具账单时却被收取了较高的利率,导致了投诉。

2.1.2测试术语

  • 测试不是调试

为了补救一个软件故障,必须对其进行定位。首先,我们只知道故障的影响,但不知道它在代码中的位置。寻找和纠正故障的过程被称为调试,是开发人员的责任。调试常常与测试相混淆,尽管这是两项截然不同的任务。调试指出了软件的故障,而测试则是用来揭示故障造成的影响。

  • 确认性测试(Confirmation testing)

纠正一个故障可以提高产品的质量(假设纠正不会引起额外的、新的故障)。用于检查故障是否已成功补救的测试被称为确认测试。测试人员通常负责确认测试,而开发人员更可能负责组件测试(和调试)。然而,这些角色在敏捷开发环境或其他软件生命周期模型中可以改变。
不幸的是,在现实世界中,故障修正常常导致新故障的产生,而这些故障只有在使用全新的输入场景时才会被发现。这种不可预知的副作用使测试更加棘手。一旦故障被纠正,你需要重复之前的测试,以确保目标故障已经被补救,你还需要编写新的测试,检查纠正过程中不需要的副作用。

  • 测试的目标:静态和动态测试是为了实现各种目标:

    • 对与需求、规范、用户故事、程序设计和代码有关的工作产品进行定性评价
    • 证明所有的具体要求已经完全实现,测试对象的功能符合用户和其他利益相关者的预期
    • 提供信息,使利益相关者能够对测试对象的质量做出可靠的估计,从而对提供的质量产生信心
    • 通过对软件故障的识别和纠正,可以降低与质量有关的风险水平。系统将包含更少的未被发现的故障。
    • 分析程序及其文件,以避免不必要的故障,并记录和补救已知的故障
    • 分析和执行程序,以便重现已知的故障
    • 接收有关测试对象的信息,以便决定有关的组件是否可以投入到与其他组件的集成中去
    • 证明测试对象遵守和/或符合必要的合同、法律和监管要求及标准。
  • 目标取决于背景

测试目标可以根据环境的不同而不同。此外,他们可以根据你使用的开发模式(敏捷或其他)和你正在执行的测试级别而变化,即组件、集成、系统或验收测试(见3.4节)。

当你测试组件时,你的主要目标应该是揭示尽可能多的故障,并尽快识别(即调试)和补救基本故障。另一个主要目标可以是选择实现最大程度的代码覆盖的测试(见2.3.1节)。

验收测试的一个目标是确认系统可以按计划运行和使用,从而满足其所有的功能和非功能要求。另一个目的是提供信息,使利益相关者能够评估风险,并就是否上线做出明智的决定。

题外话:不同类型测试的命名方案

不同类型的测试所使用的各种名称可能会令人困惑。为了理解测试的命名,区分以下的命名类别是很有用的:

  • 测试目标
    测试类型的命名是基于测试目标的(例如,"负载测试")。

  • 测试方法/技术
    例如,"状态转换测试",如5.1.3节中所述

  • 测试对象
    例如,"GUI测试 "或 "数据库测试"

  • 测试级别
    例如,"系统测试"

  • 测试人员
    例如,"开发人员测试","用户测试"

  • 测试范围
    例如,"部分回归测试"。

正如你所看到的,并非所有这些术语都定义了独特的测试类型。相反,不同的名称突出了测试的不同方面,这些方面在特定的环境下或在特定的测试目标方面是重要的或重点的。

2.1.3测试工件(Artifact)和它们之间的关系

前面的章节已经描述了一些测试工件的类型。下面几节提供了执行动态测试所需的工件类型的概述。

  • 测试基础

测试基础是测试过程的基石。如前所述,测试基础包括所有帮助我们决定测试期间是否发生故障的文件。换句话说,测试基础定义了测试对象的预期行为。常识和专业知识也可以被看作是测试基础的一部分,可以用来达成决定。在大多数情况下,需求文件,规范,或用户故事,作为测试基础。

  • 测试用例和测试运行

测试基础被用来定义测试案例,当测试对象被输入适当的测试数据并在计算机上执行时,测试运行就发生了。测试运行的结果被检查,团队决定是否发生了故障,即测试对象的预期行为和实际行为之间是否有差异。通常,为了运行一个测试案例,必须满足某些先决条件--例如,相应的数据库和数据。

  • 测试条件

测试条件是从测试基础中推断出来的,以追求特定的测试目标(见上文)。测试条件可以使用一个或多个测试来检查,可以是功能,事务,质量属性,或一个组件或系统的结构元素。在我们的案例研究中,VSR-II系统的测试条件的例子是车辆配置的排列组合(见5.1.5节),用户界面的外观和感觉,或系统的响应时间。

  • 测试项目

同样的道理,一个测试对象很少能作为一个完整的对象来测试。通常情况下,我们需要确定单独的项目,然后使用单独的测试用例进行测试。例如,VSR-II的价格计算测试条件的测试项目是calculate_price()方法(见5.1.1节)。相应的测试用例是使用适当的测试技术指定的(见第5章)。

  • 测试套件(suite)和测试执行时间表(schedules)

测试用例通常被组合在测试套件中,在一个测试周期内执行。测试周期的时间是在测试执行计划中定义的。

  • 测试脚本(Test scripts)

测试套件是使用脚本自动完成的,它包含了测试序列和所有为测试创造必要的前提条件所需的行动,并在测试完成后进行清理。如果你手动执行测试,同样的信息必须提供给手动测试人员。

  • 测试日志(Test logs)

测试运行被记录下来,并记录在测试总结报告中。

  • 测试计划

对于每个测试对象,你需要创建一个测试计划,定义进行测试所需的一切(见第6.2.1节)。这包括你对测试对象和测试技术的选择,测试目标和报告方案的定义,以及所有测试相关活动的协调。
下图显示了所涉及的各种工件之间的关系。定义测试过程中涉及的各个活动(见第2.3节)有助于明确每个工件的创建时间。
图像

2.1.4测试工作

  • 测试工作取决于项目(环境)。

测试占据了开发工作的很大一部分,即使只考虑到所有可设想的测试的一部分,或者更准确地说,所有可设想的测试案例。很难说你应该花多少精力去测试,因为这在很大程度上取决于手头项目的性质。

测试的重要性,以及测试所需的工作量,通常由测试人员和开发人员的比例来说明。在实践中,可以发现以下比例:从每10个开发人员有一个测试到每个开发人员有三个测试。在现实世界中,测试工作和预算有很大的不同。

案例研究: 测试工作和车辆变体

VSR-II使潜在客户能够在电脑屏幕上配置自己的车辆。特定车型的额外配置以及选项和预配置车型的可能组合都受制于一套复杂的规则。旧的VSR系统允许客户选择实际上无法交付的组合。作为VSR-II质量保证/测试规划要求的结果,功能适用性/DreamCar=高(见下文),客户不应该再选择不可交付的组合。
负责DreamCar模块的产品负责人想知道需要多少测试工作来尽可能全面地测试模块的这个方面。为了做到这一点,他对可用的车辆配置选项的最大数量进行了估计。结果如下:
有10种车型,每种车型有5种不同的发动机选项;有10种带夏季或冬季轮胎的轮辋;有10种颜色,每种颜色有亚光、光亮或珍珠效果选项;有5种不同的娱乐系统。这些选项导致了10×5×10×2×10×3×5=150.000种不同的变体,因此每秒钟测试一种变体将总共需要1.7天。
再加上50个额外的选项(每个选项都可以选择或不选择),总共产生150.000×250=168.884.986.026.393.600.000个变体。
产品拥有者凭直觉知道,他不需要对每个可能的组合进行测试,而是要对定义哪些选项组合是不可交付的规则进行测试。然而,可能的软件故障会产生这样的风险:DreamCar模块错误地将一些配置归类为可交付的(或允许的组合为不可交付的)。
这里需要多少测试工作,它能有效地花费多少钱?产品负责人决定向QA/测试负责人征求意见。这个问题的可能的解决方案是使用配对测试。

  • 题外话:什么时候增加测试工作是合理的?

大量的测试工作是可以承受的,也是合理的吗?Jerry Weinberg对这个问题的回答是:"与什么相比?" 。这个回答指出了使用一个有缺陷的软件系统的风险。风险是由某种情况出现的可能性和出现时的预期成本计算出来的。在测试过程中没有被发现的潜在故障会在以后产生巨大的成本。

例子: 失败的成本

2016年3月,一系列的软件故障摧毁了耗资数亿美元建造的太空望远镜Hitomi。卫星的软件错误地认为它的旋转速度太慢,并试图使用反措施进行补偿。然后,来自冗余控制系统的信号被错误地解释,旋转速度不断增加,直到离心力过大,Hitomi解体。
2018年和2019年,两架波音737 MAX 8飞机坠毁,原因是飞机的MCAS飞行控制软件存在设计缺陷。这里也是,软件--被不正确的传感器信息误导--产生了致命的对策。
测试工作必须与测试所能达到的结果保持合理的比例。"只要发现和补救故障的成本低于系统运行时发生的相应故障所产生的成本,测试就有经济意义 。因此,合理的测试工作总是取决于故障所涉及的风险程度,以及对这所带来的危险的评估。被摧毁的太空望远镜Hitomi的价格可以支付大量的测试费用。

-案例研究: 发生故障时的风险和损失

DreamCar模块持续更新并显示当前配置的价格。已注册的客户通过验证的ID可以在线订购车辆。
一旦客户点击订购按钮并输入他们的PIN码,车辆就会被订购并承诺购买。一旦过了法定的撤销期限,所选择的配置就会自动传递给生产管理系统,启动建造过程。
由于在线购买过程具有约束力,如果系统计算并显示错误的价格,客户有权坚持支付该价格。这意味着计算错误的价格可能导致制造商以过低的价格出售成千上万的汽车。根据计算错误的程度,这可能导致数百万美元的损失。让每个采购订单都进行人工检查是不可能的,因为VSR-II系统的全部意义在于,车辆可以完全自动在线订购。

  • 根据风险因素确定测试的彻底性和范围

具有高风险的系统或系统部件必须比那些在发生故障时不会造成重大损失的系统或系统部件进行更广泛的测试。必须对单个系统部件甚至单个故障模式进行风险评估。如果系统或子系统出现故障的风险很高,那么测试需要比不太重要的(子)系统更多的努力。这些程序是通过生产安全关键系统的国际标准规定的。例如,机载系统和设备认证标准规定了航空系统的复杂测试程序。

虽然不存在实质性的风险,但电脑游戏如果保存分数不正确,会给其制造商带来巨大的损失,因为这种故障会影响公众对游戏及其母公司其他产品的接受程度,并可能导致销售损失和公司的声誉受损。

2.1.5 尽早应用测试技能确保成功

  • 测试是任何成功故事中的重要因素

在软件项目中,开始准备测试永远不会太早。下面的例子说明了让具有适当测试知识的测试人员参与软件开发生命周期中的个别活动的好处:

  • 开发人员和测试人员在整个开发过程中的紧密合作
    • 如果测试人员参与检查需求(例如,使用审查,详见第4.2节)或完善用户故事,他们可以利用他们的专业知识,在工作产品中很早就发现并纠正模糊性和错误。识别和纠正有缺陷的需求,可以减少产生不适当的或不可测试的功能的风险。
    • 测试人员和系统设计人员在设计阶段的密切合作有助于所有参与人员更好地理解系统的设计和相应的测试。这种认识的提高可以减少产 生基本结构性错误的风险,并且更容易设计出适当的测试--例如,在集成测试中测试接口(见3.4.2节)。
    • 在编码阶段一起工作的开发人员和测试人员,对代码本身和它所需要的测试有更好的理解。这就减少了产生错误的代码和设计不适当的测试的风险(见6.4.1节的假阴性)。
    • 如果测试人员在发布前对软件进行验证和确认,他们肯定会发现并补救其他未被发现的故障。这就增加了产品满足其要求和满足其所有利益相关者的概率。

除了这些例子之外,实现之前定义的测试目标也将有助于成功的软件开发和维护。

2.1.6 测试的基本原则

前面几节提到了软件测试,而下面一节则总结了一般测试的基本原则。这些是经过几十年的测试经验形成的准则。

  • 原则#1:测试显示缺陷的存在,而不是缺陷的不存在

测试确定了缺陷的存在,并揭示了导致这些缺陷的故障。根据所做的努力和所涉及的测试的彻底性,测试减少了在测试对象中未被发现的缺陷的概率。然而,测试并不能使我们证明测试对象不包含故障。即使在测试过程中没有失败,这也不能证明没有故障或整体正确性。

  • 原则#2:详尽的测试是不可能的
    除了极其简单或微不足道的测试对象,不可能设计和执行一个完整的测试套件,涵盖所有可能的输入数据组合及其前提条件。测试始终是样品,分配给它们的努力取决于它们所涵盖的风险和分配给它们的优先级。

  • 原则#3:早期测试可以节省时间和金钱
    动态和静态测试活动应该在系统的生命周期内尽早定义和开始。术语 "左移 "意味着早期测试。早期测试可以在开发过程的早期阶段揭示故障。在软件方面,这有助于避免(或至少减少)在开发生命周期后期对故障进行越来越昂贵的修复。

  • 原则#4:缺陷聚集在一起

一般来说,缺陷不会均匀地分布在整个系统中。大多数缺陷通常可以在少数模块中发现,这种(估计的或观察到的)聚类效应可以用来帮助分析风险。然后,可以将测试工作集中在系统中最相关的部分(也见上述原则2)。

  • 原则之五:抗药性

随着时间的推移,测试变得不那么有效,就像昆虫对杀虫剂产生抗药性一样。如果你在一个不变的系统上重复测试,他们不会发现任何新的失败。为了使你的测试保持有效,你需要定期检查你的测试用例,如果有必要,修改它们或添加新的用例。这可以确保你测试以前未检查的组件和以前未测试的输入数据,从而揭示这些产生的任何故障。杀虫剂悖论也可以产生积极的影响。例如,如果自动回归测试显示出低数量的故障,这可能不是软件质量高的结果,而是由于使用中的(可能是过时的)测试案例的无效性。

  • 原则#6:测试是依赖于环境的

测试需要适应所提出的目的和有关系统的周围环境。没有两个系统能以同样的方式进行有效测试。测试的彻底性、退出标准和其他参数需要根据系统的工作环境进行独特的定义。一个嵌入式系统需要不同的测试,例如,一个电子商务系统。敏捷项目的测试与基于顺序生命周期模型的项目的测试将有很大不同。

  • 原则7:不存在错误是一种谬论

即使你全面地测试了所有的需求,并且纠正了所有发现的错误,仍然有可能开发出难以使用的系统,不能满足用户的期望,或者与其他类似的系统(或同一系统的早期版本)相比,质量很差。原型设计和系统用户的早期参与是用来避免这个问题的预防措施。

2.2软件质量

软件测试的作用是识别和补救故障,提高软件质量。测试案例的选择应该反映系统设计的后续真实世界的使用情况。测试所验证的质量应该等同于用户体验的质量。
然而,软件质量不仅仅是纠正测试中发现的故障。
ISO 25010: 使用质量模型和产品质量模型

2.2.1根据ISO 25010的软件质量

根据ISO 25010标准[ISO 25010],软件质量可以从两个主要方面进行分类:使用质量模型和产品质量模型。

使用中的质量模型包括以下五个特征:

  • 有效性
  • 效率
  • 满意度
  • 低风险
  • 周境覆盖

产品质量模型包括八个特征:

  • 功能适用性
  • 性能效率
  • 兼容性
  • 易用性
  • 可靠性
  • 安全性
  • 可维护性
  • 可移植性

产品质量模型与之前的ISO 9126标准有最大的相似之处。数据质量模型的细节可以在ISO 25012标准中找到。
为了有效地判断一个软件系统的质量,所有这些特性和质量标准都需要在测试过程中加以考虑。测试对象的每个特征所要达到的质量水平必须事先在质量要求中定义。这些要求和标准的满足情况必须通过适当的测试来检查。

质量模型25010_20130729_完整版.docx: https://url97.ctfile.com/f/18113597-854695755-a34349 (访问密码: 2274)

ISO 25010将上面列出的13个质量特性细分为总共40个子特性。详细介绍使用中的质量和产品质量模型的所有40个子特征,超出了本文的范围。一些比较重要的特征总结如下:

  • 功能适合性(Functional suitability)

功能完整性(Functional Completeness):软件产品实现的功能达到所有指定任务和用户目标的程度。功能集是否涵盖所有指定的任务和用户目标?
功能正确性(Functional Correctness):软件产品提供具有所需精度的正确或者相符的结果的程度。产品/系统是否以要求的准确度提供正确的结果?
功能适当性(Functional Appropriateness):软件产品促进完成指定任务和目标的程度。可用的功能在多大程度上完成了所需的任务和指定的目标?

适当的测试可以用来检查指定和隐含的要求是否反映在可用的功能中,从而回答上面提出的问题。
功能通常被描述为特定的输入/输出行为和/或特定的系统对特定输入的反应。测试的目的是为了证明每个所需的功能已经以这样的方式实现,即指定的输入/输出行为或系统行为得到遵守。

  • 可靠性(Reliability)

成熟度(Maturity):软件系统、产品或组件在正常运行下满足可靠性要求的程度。在正常工作条件下,一个系统、产品或部件在多大程度上提供所需的可靠性?
可用性(Availability):软件系统或产品在使用时可操作和可访问的程度。系统、产品或部件是否总是可以使用,以及在需要时是否容易获得?
容错性(Fault tolerance):尽管存在硬件或软件故障,但软件系统、产品或组件仍然按照预期运行的程度。尽管存在已知的硬件或软件故障,系统、产品或组件的功能如何?
易恢复性(Recoverability):当发生中断或故障时,软件产品或系统能够恢复直接受影响的数据并重新建立系统所需状态的程度。在系统或产品发生故障或崩溃后,需要多长时间才能恢复特定数据和正常服务?

  • 满意度

使用中的质量模型的满意度是指在特定情况下使用产品或系统时,用户需求被满足的程度。这个质量特征有四个子特征:
有用性:用户满意程度是他们认为达成务实的目标,包括使用结果和使用影响。用户对感知到的实用目标的实现有多高兴,包括使用该系统的结果和后果?
信任:用户或其他利益相关者对一个产品或系统的行为为目的信心程度。用户(或其他利益相关者)对产品或系统的行为是否符合预期有多确定?
有趣:用户从满足他们的个人需求中获得乐趣的程度。当用户使用该系统来满足他/她的个人要求时,他/她能体验到多少乐趣?
舒适:用户对身体舒适的满意程度。用户觉得这个系统有多舒适--也包括身体健康方面?

使用质量模型的大多数特征都有很强的个人因素,只有在特殊情况下才能客观地看待和精确地评价。为了测试这种质量特性,你需要参考多个用户(或用户组),以便获得可用的测试结果。

一个软件系统不可能在同等程度上满足所有的质量特性。满足一个特性往往意味着不能满足另一个特性。一个高效的软件系统并不容易移植,因为它的开发者会设计它来利用它所运行的平台的特定属性。

  • 确定质量特征的优先次序

因此,有必要对这些特性进行优先排序。由此产生的优先级也将作为每个特性的测试彻底性的准则。

案例研究: 将ISO 25010应用于VSR-II

VSR-II的测试/QA负责人向项目指导委员会建议使用ISO 25010中描述的产品质量模型。委员会同意并要求测试/QA负责人准备一份概念文件,说明如何在VSR-II项目中应用该标准。草案的核心是一个矩阵,说明每个质量属性与每个产品组件的相关性,以及应用哪些解释。矩阵的初始草案看起来像这样:

这些风险分类要解释,并由每个质量特性的测试/质量保证负责人进行论证,例如:

  • 功能适用性/所有模块

每个模块都为大量的用户服务,并处理大量的数据,所以功能故障有可能产生相当大的成本。因此,该要求对所有模块都被归类为 "高"。

  • 兼容性/连接的汽车
    没有要求,因为这个模块要从头开始建立。

  • 可用性/事实书
    没有要求,因为这是一个后端模块,API已经存在。

  • 可移植性/DreamCar
    这个特性被归类为 "低",因为正在使用的框架涵盖了它,不需要应用额外的措施。

哪些检查和测试是需要的,将在每个模块的质量保证/测试计划中确定。这种顶层分类可以用来建立基本参数--例如,自动化的持续集成测试(见3.2节)对 "高 "特性是必需的,单轮验收测试对 "中 "特性是足够的,而关于团队如何处理问题的书面设计指南对 "低 "特性是足够的。QA/测试负责人肯定要与各团队进行多轮评估,以便就这些高级别的规则达成一致。

2.2.2 质量管理和质量保证

  • 质量管理

质量管理(QM Quality management)包括所有用于控制质量的组织活动和措施。质量管理通常负责确定质量政策、质量目标、质量规划、质量保证和质量改进。这使得质量管理成为一项核心管理活动。质量管理在航空、汽车和医疗保健等行业是强制性的。

  • ISO 9000

ISO 9000系列的质量管理标准[ISO 9000]被广泛使用,ISO/IEC 90003软件工程标准[ISO 90003]规定了如何将ISO 9001[ISO 9001]的一般准则应用于计算机软件。

  • 质量保证

质量保证(QA Quality assurance)通常集中在一些措施上,这些措施旨在确保指定的程序得到应用,定义的过程得到遵守。假设一个公司坚持其预定的流程,它将满足所需的质量特性,从而达到指定的质量水平。在这种情况下,结果通常会显示出质量的提高,这反过来有助于避免工作产品和相应文件的失败。

  • QA和测试

术语 "质量保证 "在提到测试过程时经常被使用,甚至作为测试的同义词。QA和测试过程密切相关,但绝对不一样。QA产生对质量要求的满足的信心,这可以通过测试来实现。有效的QA还包括分析各种缺陷的原因,并用于识别(测试)和补救(调试)它们。其结果在被称为 "回顾 "的会议上进行讨论,并可用于改进相关流程。因此,测试的作用是证明所要求的质量水平已经达到。

测试活动是整个软件开发和维护过程的一部分,由于QA是为了确保这些过程被正确实施和执行,QA也支持有效的测试。下一节将更详细地描述测试过程本身。

2.3 测试过程

  • 开发模型

第3章介绍了不同类型的软件开发生命周期模型(也更简单地称为 "开发模型")。这些都是为了帮助新的或持续的软件项目的结构化、规划和管理。为了进行结构良好的测试,你通常需要的不仅仅是对构成开发模型的活动的描述。除了在整个开发过程中对测试进行定位外,你还需要一个详细的专门的测试时间表。换句话说,被称为 "测试 "的开发任务的内容需要被分解成更小、更容易管理的步骤。
测试包括一连串的单独活动

有许多广泛使用的、经过验证的测试活动,测试过程将由这些种类的活动组成。你需要根据指定的(或继承的)项目情况,组建合适的测试过程。你选择的具体测试活动,以及你如何(和何时)实施它们,将取决于许多因素,并且通常基于公司或项目特定的测试策略(见6.2节)。如果你忽略了某些测试活动,你将增加测试过程不能达到其目标的可能性。

  • 主要活动

测试过程一般包括以下活动:

  • 测试计划
  • 测试监测和控制
  • 测试分析
  • 测试设计
  • 测试实施
  • 测试执行
  • 测试完成

这些活动中的每一项都包括多个单独的任务,它们产生各自的产出,并根据手头的项目在性质上有所不同。

  • 迭代测试

即使测试过程中涉及的各个任务是按逻辑顺序定义的,在实践中,它们可以(也可能)重叠,有时也会同时进行。即使你打算按照预定的顺序进行测试活动,顺序开发模式(例如,"瀑布 "模式)也会导致个别活动或部分活动的重叠、组合、并发或取消。
调整这些活动以适应系统和项目背景(见下文)通常是必要的,无论你使用哪种开发模式。

软件通常是以小的迭代步骤开发的--例如,敏捷开发方法使用连续的构建和测试迭代。因此,相应的测试活动也需要连续和迭代地进行。
下面的章节概述了各个测试步骤和它们的输出。测试管理负责监测和执行这些活动中的大部分,在第6章中详细描述(见第6.2和6.3节)。

2.3.1测试计划

如果没有一个计划,像测试这样广泛的任务的结构化处理将无法进行。测试计划在软件项目开始时就直接开始。像任何计划一样,有必要定期审查你的测试计划,并更新或调整它以适应不断变化的情况和项目参数。因此,测试计划是重复的活动,在整个产品生命周期中进行,如果有必要的话,可以进行调整。

  • 测试计划:规划内容

规划测试时的主要任务是根据你选择的测试策略创建测试计划。这个测试计划定义了测试对象、质量特征和测试目标,以及你计划用来验证它们的测试活动。因此,测试计划描述了你的测试技术,所需的资源,以及执行相应测试活动所需的时间。

  • 覆盖率标准

你已经进行了充分的测试,这一点由计划的覆盖率决定,也是测试计划的一部分。这种标准通常被称为 "完成标准 "或 "退出标准",或者在敏捷项目中被称为 "完成定义"。如果为每个测试级别或类型定义了覆盖标准,你可以客观地评估你所进行的测试是否可以被视为足够。覆盖标准也可以用来监测和控制测试,它们还可以验证你何时达到了你的测试目标。

测试计划还包含测试基础的信息,它是你所有测试考虑的基石。测试计划还需要包括有关测试基础和测试活动结果之间的可追溯性信息。例如,这可以帮助你确定哪些测试基础的变化修改了哪些测试活动,从而使你能够适应或增强它们。

测试计划还定义了哪些测试要在哪个测试级别进行(见3.4节)。为每个测试级别起草一个单独的测试计划通常是有意义的,你可以用一个主测试计划将这些计划汇总到一起。

  • 测试计划:日程安排(Schedule)

测试计划包含了测试过程中涉及的所有活动、任务和/或事件的清单。这个列表包括每个活动的计划开始和结束时间。活动之间的相互依存关系在测试时间表中指出。

该计划还定义了关键活动的最后期限,以支持其在项目期间的实际执行。测试时间表可以是测试计划的一部分。

2.3.2测试监控和控制

  • 确保可追溯性

监测和控制包括不断观察当前测试活动与计划活动的比较,报告任何差异,以及在变化的情况下执行实现计划目标所需的活动。计划的更新也必须以变化的情况为基础。

  • 退出标准是否得到满足?

测试监测和控制活动是以每项活动或任务的退出标准为基础的。对某一特定测试级别的测试退出标准是否已经实现的评价可以包括
a.根据可用的测试结果和日志,达到测试计划中定义的覆盖程度。如果预定的标准得到满足,活动就可以终止了。
b.根据测试结果和日志,确定所需的组件或系统质量。如果所要求的质量已经达到,测试活动就可以结束。
c.如果风险评估是测试计划的一部分,你需要证明你有足够的风险覆盖,这也可以用测试结果和日志来确定。

  • 执行额外的测试或承担风险?

如果你所进行的测试没有达到要求的退出标准,你需要设计和执行额外的测试。反之需要澄清情况并评估随之而来的风险。

  • 进度和完成报告

利益相关者希望收到定期的测试进度报告,与整体计划相比,当前的测试进度。除了与原计划的任何偏差,这些报告还应该包含有关任何过早终止的测试(见上文)或未完成计划的退出标准的信息。在达到项目里程碑时,应提供测试总结报告。
所有的测试报告都应包含与接受者相关的细节,并包括进度报告以及测试结果。报告还应该回答或预先回答管理问题,如(预期)结束时间,计划与实际使用的资源,以及涉及的测试工作量。
进度监测可以基于团队成员的报告,也可以基于自动化工具提供的数字和分析。

2.3.3测试分析

  • 我们需要测试 "什么"?

测试分析包括确定到底需要测试什么。为此,要检查测试基础,看要使用的文件是否足够详细,是否包含可测试的功能,以便得出测试条件。测试条件需要被检查的程度是由可衡量的定义的覆盖标准决定的。
以下文件和数据可以用来分析测试基础和计划的测试水平:

  • 分析测试的基础

规定了计划中的功能性和非功能性的系统或组件行为的要求。需求规格包括技术需求、功能需求、系统需求、用户故事、史诗1、用例和类似的工作产品或文档。例如,如果需求没有足够精确地指定预测的结果和/或系统行为,那么测试用例就不能简单地导出。必须进行重做。

  • 分析文档

引起特定组件或系统结构的设计或实现数据、系统或软件架构文件、设计规范、调用图、模型图(例如,UML或实体关系图)、接口规范以及类似的材料都可以用来作为测试基础。例如,你需要分析接口如何容易被处理(接口开放性),以及测试对象如何容易被划分为较小的子单元,以便分别测试这些。你需要在开发阶段考虑这些方面,测试对象也需要相应的设计和编码。

  • 检查测试对象

你需要调查各个组件或系统本身,包括代码库、数据库元数据、数据库查询和其他接口。例如,你需要检查代码的结构是否良好,是否容易理解,所要求的代码覆盖率(见5.1节)是否容易实现和验证。

  • 风险分析

涵盖系统或其组成部分的功能、非功能和结构方面的风险分析报告也需要进行调查。如果潜在的软件故障造成了严重的风险,测试也需要相应的彻底。对于不属于关键任务的软件,可以不那么正式地进行测试。

  • 潜在的文档错误

整个测试过程的基石是测试基础。如果测试基础包含缺陷,你就不能制定 "正确的 "测试条件,也就不能起草 "适当的 "测试案例。因此,你也需要分析测试基础的缺陷。检查它是否包含歧义,或者在功能描述中是否有空白或遗漏。你需要检查文档中的不一致、不精确、矛盾,以及重复和/或多余的段落。你发现的任何缺陷或差异都应立即纠正。

从测试基础上发现和消除缺陷是非常重要的,特别是在文档还没有被审查的情况下(见4.3节)。行为驱动开发(BDD)和验收测试驱动开发(ATDD)等开发方法,在编码开始前使用验收标准和用户故事来创建测试条件和测试案例。这种方法使得在开发过程的更早阶段识别和补救缺陷更加简单。

  • 确定测试的优先次序

一旦测试条件被识别和定义,你需要对它们进行优先排序。这可以确保最重要的和高风险的测试条件被首先测试。在现实世界中,时间的限制往往使得不可能执行所有计划的测试。

  • 可追溯性很重要

在计划阶段,你需要确保在测试基础和测试活动的结果之间有明确的双向可追溯性(见上文)。这种可追溯性必须精确定义哪个测试条件检查哪个需求,反之亦然。
这是确保你以后能确定哪些需求需要被测试的彻底性的唯一方法,并且取决于测试条件--使用哪些测试案例。

  • 选择测试技术

在分析阶段考虑使用哪种测试技术(即黑盒,白盒,基于经验,见第5章)是很有用的。每种技术都有自己的系统,可以减少忽视测试条件的可能性,并帮助精确定义这些条件。例如,使用等价分区(或 "等价类")测试(见第5.1.1节)确保整个输入域被用于创建测试用例。这可以防止你在需求定义中忘记或忽略了负面的输入。然后,你可以定义你的测试条件来涵盖负的输入数据。
如果你使用基于经验的测试技术(见第 5.3 节),你可以使用分析期间定义的测试条件作为你的测试章程的目标。测试章程是一种 "任务",与传统的测试目标一起,为额外的测试提供潜在的想法。如果测试目标可以追溯到测试基础,你可以评估所实现的覆盖率(例如,对于你的需求),甚至当你使用基于经验的技术。

2.3.4 测试设计

如何测试和使用哪些测试用例

当设计测试时,你要确定如何进行测试。在设计阶段,测试条件被用来创建测试用例(或测试用例的序列)。在这里,你通常会使用第五章中详述的测试技术之一。

  • 抽象和具体的测试用例

抽象的(或 "高层次的")测试用例不包括具体的输入值或预期结果,并使用逻辑运算符描述。这种案例的优点是,它们可以在多个测试周期中使用,并使用不同的数据,但仍然可以充分记录每个案例的范围。具体的(或 "低级")测试案例使用具体的输入数据和预期结果值。
当你开始设计一个测试时,你可以使用抽象的以及具体的测试用例。因为只有具体的测试用例可以在计算机上执行,抽象的测试用例必须要有真实的输入和输出值来充实。为了利用抽象测试用例的优势(见上文),你也可以从具体用例中导出抽象测试用例。

  • 测试用例涉及的不仅仅是测试数据

每个测试用例都必须定义先决条件。测试也需要明确的约束条件,必须遵守。此外,你需要事先确定你期望测试产生什么结果或行为。除了输出数据,结果包括对全局(持久)数据和状态的任何变化,以及对测试用例执行的任何其他反应。

  • 测试神谕(oracle)

你需要使用足够的资源来预测测试结果。例如,规范可以作为神谕。有两种基本方法:

a.测试人员根据测试基础中定义的测试对象的要求和规格,从输入值中得出预期输出值。
b.如果逆函数存在,你可以执行逆函数并将其输出与原始测试案例的输入值进行比较。例如,这种技术可以在测试加密和解密算法时使用。

下面的例子说明了抽象和具体测试用例之间的区别。
案例研究: 抽象和具体的测试用例

一家经销商可以让其销售人员选择折扣,以适用于车辆的价格。对于低于15,000美元的价格,没有折扣。对于价格在20,000美元以下的,适合5%的折扣。如果价格低于25,000美元,可以有7%的折扣。如果价格高于25,000美元,则应采用8.5%的折扣。
通过以上文字,我们可以得出价格和折扣之间的关系如下:
价格<15,000
折扣=0%。
15.000 ≤ 价格 ≤ 20,000
折扣=5%。
20.000 < 价格 < 25,000
折扣=7
价格≥25,000
折扣=8.5

文本本身显然提供了解释的可能性。换句话说,文本可能会被误解,而从文本中得出的数学公式是明确的。
基于这些公式,我们可以定义以下测试案例:

为了执行这些测试,抽象的案例必须转换为具体的案例--也就是说,我们必须应用具体的输入值(见表2-3)。这里不包括例外条件和边界案例。

这里显示的数值只是为了说明抽象和具体测试案例之间的区别。我们没有使用特定的测试技术来设计这些测试,所显示的案例也不是为了详尽地测试折扣组件。例如,没有一个测试用例涵盖错误的输入(如负数的价格)。你会在第5章中找到更多关于使用特定测试技术系统地创建测试案例的细节。

除了指定抽象和具体的测试用例外,测试设计还包括对你的测试用例进行优先排序,并提供适当的测试基础设施:

  • 优先级和可追溯性

测试分析已经对测试条件进行了优先排序。这些相同的优先级可以用于你的测试用例(或测试用例集)并进行微调。这样,你可以在一组测试中为个别测试分配不同的优先级,这些测试是为了验证一个测试条件。高优先级的测试首先被执行。
同样的原则也适用于测试条件的可追溯性,它可以被分解为涵盖单个测试案例或案例集。

  • 测试基础设施和环境

必须对所需的测试基础设施进行评估和实施。测试基础设施包括测试所需的所有组织元素。这些包括测试环境、测试工具和适当配备的工作站。为了在计算机上运行测试对象并验证指定的测试案例(见下文),需要一个测试环境。这个环境包括硬件、任何必要的模拟设备和软件工具,以及其他支持材料。为了避免测试时的延误,在测试开始前,测试基础设施应该建立和运行(和测试)。
在测试分析之后,测试设计阶段可以发现测试基础的进一步缺陷。同样地,在分析阶段定义的测试条件可以在设计阶段进行微调。

2.3.5测试实施

  • 一切准备就绪,可以开始测试了吗?

测试实施的任务是所有必要活动的最后准备,以便在下一步可以执行测试用例。测试设计和测试实施活动通常是结合在一起的。

  • 巩固测试基础设施

实施过程中的主要任务之一是创建和整合所有的测试软件,特别注意测试基础设施的细节。测试框架必须安装在测试环境中。检查环境是极其重要的,因为测试环境的故障会导致系统故障。为了确保测试没有延迟或障碍,你还需要检查所有额外的工具(如服务虚拟化、模拟器和其他基础设施元素)是否到位和工作。

  • 巩固你的测试案例

为了确保你的具体测试案例可以在没有进一步改变或修正的情况下使用,所有的测试数据必须正确地转移到测试环境。抽象的测试案例必须要有具体的测试数据。
除了确定你的测试用例,你还需要定义测试程序本身--即,计划的测试必须被放入逻辑序列。这是根据你定义的优先级进行的(见6.2节)。

  • 测试套件,测试程序,测试脚本

为了保持测试周期的有效性,并保留一个逻辑结构,测试用例被分组为测试套件。测试套件由多个测试组成,根据计划的执行顺序分组。顺序的规划使一个测试用例的后置条件成为下一测试用例的前提条件。这简化了测试程序,因为它省去了每个测试用例的专用前条件和后条件的需要。一个测试套件还包括执行完成后所需的清理活动。
与手工测试相比,使用脚本自动测试程序可以节省大量的时间。
计划执行测试用例、测试套件和测试程序的最有效方法是在测试执行计划中定义的(见第6.3.1节)。
你的测试用例与需求和/或测试条件的可追溯性需要被检查,如果有必要,需要更新。在检查可追溯性时,测试套件和程序也必须被考虑在内。

2.3.6 测试执行

  • 完备性检查

首先检查你要测试的所有组件和相应的测试软件是否可用是很有意义的。这包括在测试环境中安装测试对象,并检查它是否可以启动和运行。如果这个检查没有发现任何障碍,就可以开始测试。

测试的执行应该从检查测试对象的主要功能开始(见5.1.6节的其他技术旁注中的 "烟雾测试 "部分)。如果这发现了故障或与预期结果的偏差,你需要在继续测试之前补救相应的缺陷。

  • 没有日志的测试是没有价值的

测试执行过程--不管是手动的还是根据测试执行计划自动进行的--都必须精确和完整地记录下来。你需要记录每一个测试结果(即,通过,失败,阻塞),以便那些没有直接参与测试过程的人(例如,客户)可以理解。日志还有助于验证整个测试策略(见6.2节)是否按计划执行。日志应该显示哪些部分被测试了,什么时候,由谁来测试,测试的强度如何,结果如何。如果计划中的测试用例或测试序列由于任何原因被遗漏,这也需要被记录下来。

  • 明确性和可重复性的重要性

除了测试对象(或测试项目),还有一大堆文件和其他信息参与测试的执行。这些包括:测试框架、输入数据、日志等等。与测试用例或测试运行有关的数据和其他信息必须得到管理,以便以后可以使用相同的数据和约束条件轻松地重复测试。使用的工具的ID和/或版本号应该由配置管理来注意和记录(见6.5节)。

  • 真的有失败吗?

如果预期结果和实际结果之间存在差异,评估测试日志将帮助你决定这是否真的是由于失败造成的。如果你确实发现了故障,在你开始寻找其原因之前,请确保你将其记录下来。可能有必要指定和执行补充测试用例。你也应该报告这个缺陷。关于测试记录的更多内容,请参见第6.4.1节;关于缺陷报告的更多内容,请参见第6.3.4节;关于缺陷管理的一般讨论,请参见第6.4节。

  • 重新测试

一旦BUG修复,你需要检查相应的故障是否也被解决了,并且纠正过程没有引起新的故障。你可能需要指定新的测试用例来验证修改后的代码。

你需要仔细检查一个故障是否真的是由测试对象引起的。对测试人员的声誉来说,没有什么比报告的故障实际上是一个有缺陷的测试用例更糟糕的了。同时,你必须注意不要对这种情况过度警惕,你不能害怕报告潜在的失败,即使你不确定其原因。这两种情况对项目都是不利的。

  • 单独的故障纠正是不实际的

理想情况下,你将单独纠正故障,并重新测试,以确保你的纠正不会无意中相互影响。然而,这种方法在现实世界中根本不实用。如果测试是由独立的测试人员而不是开发人员执行的,那么单独的修正就不可能了。向开发者报告每个错误,并在重新测试之前等待这些错误被纠正,这不是合理的努力。通常的做法是纠正一系列的故障,然后建立一个新版本的软件进行测试。

除了记录预期和实际结果之间的差异外,你还需要评估覆盖率,如果有必要,还要记录测试的运行时间。有专门的工具可用于这些任务(见第7章)。

  • 追踪性在这里也很重要

到目前为止,双向跟踪是所有测试活动的一个重要部分,我们已经看过了。在这里,你也需要检查可追溯性,如果有必要,更新系统,使测试基础和测试条件、案例、测试运行和结果之间的关系是最新的。一旦测试序列完成,你可以使用其内置的可追溯性来评估测试基础中的每一个项目是否已经被相应的测试过程所覆盖。

  • 测试目标实现了吗?

这样,你可以检查哪些需求已经通过了计划和执行的测试,哪些需求由于测试失败或测试过程中登记的失败而不能被验证。你可能会发现,一些需求还没有被验证,因为相应的测试还没有被执行。这类信息使你能够验证计划的覆盖标准是否已经完成,因此测试是否可以被视为成功完成。

有效的覆盖标准和可追溯性使你能够记录你的测试结果,使它们对项目的所有利益相关者来说都是容易理解的。

其他常见的退出标准在6.3.1节中讨论。

2.3.7测试完成

  • 测试完成的正确时间

测试完成是测试过程中的最后一项活动,包括整理已完成的测试活动所收集的所有数据,以评估测试经验,并巩固测试软件及其相关材料。测试完成的正确时刻根据你使用的开发模式而不同。它可以是:
系统上线时;测试项目的结束(或中止);敏捷项目迭代的完成(例如,作为回顾或审查会议的一部分);某一特定测试级别的测试活动的完成;维护版本的测试活动的完成;

在完成时间,你还需要确保所有计划的活动已经完成,并且缺陷报告是完整的。open的或未解决的故障(即未解决的与现有需求的偏差)仍然是open的,并延续到下一个迭代或发布。在敏捷环境中,这种未解决的案例被归类为新的产品积压项目,以纳入下一个迭代中。

对测试结果的评估所产生的变更请求和修改需求也是类似的处理方式。

  • 测试总结报告

测试总结报告(见第6.3.4节)汇总了你所有的测试活动和结果,并包括对你所进行的测试与你预定的退出标准进行的总体评价。总结报告会分发给所有利益相关者。

  • 归档测试件

软件系统一般会被长期使用,在这期间会出现在测试中没有发现的故障。在其生命周期中,系统也会受到其用户(或客户)的变更要求。这两种情况都意味着系统必须被重新编程,修改后的代码必须被重新测试。如果你原来使用的测试软件(测试用例、日志、基础设施、工具等)仍然可用,并且可以移交给维护部门,那么这种维护所涉及的很大一部分测试工作是可以避免的。这意味着,在进行系统维护时,只需对现有的测试软件进行调整,而不是从头开始设置。测试软件也可以在类似的项目中使用,并从中获利。对于一些行业,法律要求提供测试证明,而这只有在所有的测试软件被适当归档时才能提供。

测试后保存测试软件是非常费力的,所以测试人员经常捕捉测试环境的图像或使用Docker免费软件来创建容器--一个容易运输和可重复使用的文件,包含所有的相关资源,可以作为一个独立的测试环境安装和运行。

  • 从经验中学习

你在测试时收集的经验可以在未来的项目中进行分析和使用。你的计划和你实际进行的活动之间的偏差和寻找其原因一样有趣。你应该利用你的发现来释放你的改进潜力,并对你在未来的迭代、发布和项目中进行的活动进行修改。这些变化有助于整个测试过程的成熟。

2.3.8 可追溯性

  • 测试基础和测试结果之间的可追溯性

当我们谈论测试活动时,我们经常提到可追溯性的重要性。下面的章节总结了测试基础和测试结果之间的可追溯性,并详细介绍了有效追溯的其他优点。
可追溯性对于跨越整个测试过程的有效测试监测和控制至关重要。它建立了测试基础中每个项目和各种测试结果之间的关系。可追溯性帮助你评估你实现的覆盖程度--例如,检查是否所有的需求都被至少一个测试案例所覆盖。这样的可追溯性数据有助于你控制测试过程的整体进度。
除了检查覆盖率之外,有效的可追溯性还支持以下几个方面:
可追溯性有助于评估变化的影响,通过分析需求的哪些变化影响哪些测试条件、测试运行、测试用例和测试项目

  • 更高的、抽象的层次

可追溯性使你能够将你的结果提升到一个 "更高 "的抽象水平,从而使测试过程更容易被非专业人员所理解。只考虑已执行的测试用例并不能提供关于测试过程有多彻底或广泛的信息。只有当你包括可追溯性信息时,输出才会对所有相关的利益相关者群体变得可理解。这也有助于实现抽象的IT管理标准。

同样的论点也适用于测试进度和测试总结报告--也就是说,有效的可追溯性使它们更容易理解。测试基础中每个项目的状态都应该包括在报告中。对于每个单独的需求,可以做以下的一个陈述:
测试通过了;测试失败,出现故障;计划中的测试还没有执行。

可追溯性也使我们能够使所有利益相关者理解测试的技术方面。以公司目标为尺度,它使他们能够评估产品质量、程序能力和项目进展。

  • 基于工具的支持

为了最好地利用可追溯性的优势,一些公司建立专门的管理系统,以自动提供可追溯性数据的方式组织测试结果。有各种测试管理工具可以使用,这些工具本身就实现了可追溯性。

2.3.9 上下文对测试过程的影响

  • 测试过程的背景

以下是影响组织内测试过程的一些因素(也见6.2.5节):

测试活动的选择和使用取决于你使用的软件开发生命周期模型。大多数敏捷模型并不包括测试及其相关活动的详细指导。
根据选择和实施的系统结构,系统可能被划分为子系统。这影响到测试级别(组件、集成、系统和验收测试--见第3.4节)和用于导出或选择测试用例的相应技术(见第5章的测试技术)。
测试类型也影响着测试过程。测试类型是一组测试活动,旨在测试组件或系统的相互关联的质量特性。测试类型通常集中在单一的质量特性上,例如,负载测试(见第3.5节)。
在产品或项目存在重大风险的情况下,测试过程需要设计成通过测试用例来解决最大数量的风险,从而使风险最小化(见6.2.4节)。
软件系统的使用环境也会对测试过程产生影响。例如,专门用于公司内部度假计划的软件,与为控制客户的工业设施而建立的定制系统相比,要接受更彻底的测试。
公司准则和最佳实践也会对测试过程和规则产生影响。这里的好处是,影响过程的因素不需要为每个项目进行讨论和重新定义。要求的内部和外部标准具有相同的效果。

  • 操作上的限制

操作上的限制也会影响测试过程的结构和实施。这种限制包括:
预算和其他资源(例如,专业人员),这些资源通常在测试方面是短缺的
最后期限延长,留给测试的时间比计划的少

要测试的系统的复杂性。复杂的系统是不容易测试的! 测试过程的设计必须反映系统的复杂性。
合同和法规要求。这些对测试过程的范围有直接的影响,因此对所涉及的个别活动也有影响。

2.4 人类心理学对测试的影响

  • 人性本善

每个人都会犯错,但没有人喜欢承认错误!软件测试的主要目的是揭示与规范和/或客户要求的偏差。所有发现的失败都必须传达给开发人员。下面的章节将讨论如何处理可能导致的心理问题。
软件开发通常被看作是一种建设性的活动,而测试产品和检查文档则更多地被看作是破坏性的。这种观点常常导致参与项目的人对他们的工作有非常不同的态度。然而,这种假设是完全没有道理的,因为根据[Myers 12, p. 13, 软件测试原则#10]: "测试是一项极具创造性和智力挑战的任务"。此外,测试对项目的成功和最终产品的质量起着重要作用(见2.1节)。

  • 披露错误

发现的故障必须传达给有问题的文件或源代码的作者。管理层也需要知道哪些(或至少有多少)缺陷是通过测试发现的。这种沟通方式对分析师、产品所有者、设计师、开发人员和测试人员之间的关系有好处,但也会对这些重要的沟通渠道产生负面影响。承认(或证明)错误不是一件容易的事情,需要有很大的敏感性。

发现故障可以被理解为对产品或其作者的批评,并且可以作为静态或动态测试的结果。这种情况的例子有:
讨论需求文件的评审会议;讨论用户故事的会议,并对其进行微调;在动态测试执行期间;始终考虑到确认偏差

"确认偏差 "是一个心理学术语,描述了以证实或加强你先前的个人信念或假设的方式搜索、解释、赞成和回忆信息的倾向。这种倾向在软件故障的交流中起着重要作用。软件开发者通常认为他们的代码是没有错误的,确认性偏见使他们很难承认他们的工作可能有缺陷。其他认知上的先入为主,也会使相关人员在理解或接受软件测试的结果方面感到棘手。

  • 认识到的缺陷是一件积极的事情

另一个彻底的人类特征是倾向于 "射杀 "带来坏消息的信使。测试结果常常被看作是坏消息,尽管事实往往相反:公认的缺陷可以被补救,测试对象的质量可以得到改善。公开的软件故障实际上是一件积极的事情!"!

  • 需要的软技能

为了避免(或至少减少)这种冲突的可能性,测试人员和测试经理需要发展良好的软技能。只有这样,参与的每个人都能有效地讨论故障、失败、测试结果、测试进展和风险。相互尊重总是能创造一个积极的工作环境,并在所有参与项目的人之间产生良好的关系。

  • 积极沟通的例子

争论或简单的 "吵闹 "对工作场所的合作绝非好事。为了确保工作的友好进展,提醒每个人他们的共同目标和他们所追求的高质量产品往往是有帮助的。
正如已经提到的,你永远无法重复发现一个缺陷并纠正它是一件积极的事情。其他积极的方面有:
错误识别可以帮助开发人员改善他们的工作,因此也可以改善他们的结果。很多开发人员没有意识到,测试结果可以帮助他们磨练自己的技能。
发现并改正的错误最好向管理层提出,作为节省时间和金钱的手段,并作为减少产品质量差的风险的方法。
保持文件的中立性和事实性

文档风格在沟通中也起到了一定的作用。测试结果和其他发现需要被中立地记录下来,并应坚持以事实说话。如果一个文件有缺陷,不要批评它的作者。总是写客观的、基于事实的缺陷报告和审查结果。
始终考虑对方的观点。这样可以更容易理解为什么有人也许对你写的或说的东西有负面的反应。

一般来说,误解和交头接耳从来不会产生建设性的沟通。如果你发现自己处于这种情况(或预计会出现这种情况),一定要问你说的话是如何被理解的,并确认实际说的是什么。这在两个方向都适用。
2.1.2节列出了典型的测试目标。明确的目标也有明显的心理作用。人们通常喜欢将自己的行为与明确定义的目标相一致。除了测试目标外,你可以把自己定位在团队目标、管理目标或其他利益相关者的目标上。重要的是,测试人员要尽可能公正地追求和坚持这些目标。

2.4.1 测试人员和开发人员如何思考

  • 不同的思维方式

由于他们追求的目标非常不同,开发人员和测试人员的思维方式通常也很不同。开发人员设计和生产产品,而测试人员验证和确认产品,以发现错误和故障。通过结合这两种不同的思维方式来提高产品质量是可能的。
假设和首选的决策技术反映在大多数人的思考方式中。除了好奇心,测试人员的心态通常会包括健康的职业悲观主义水平,并结合对测试对象的批判性看法。对细节的兴趣和与每个人积极沟通的意愿是对测试人员有用的其他特征。测试人员通过多年的实践经验发展他们的软技能。
开发者的主要兴趣是设计和实现问题的解决方案,所以他不会热衷于考虑解决方案的哪些方面有缺陷或错误。尽管开发人员的心态的某些方面与测试人员相似,但上述的确认偏见总是使开发人员更难认识到他们自己工作中的错误(参见6.1.1节)。

题外话

开发人员可以改变他的心态并测试自己的软件吗?这个问题没有简单的答案,既开发又测试产品的人需要对自己的工作有罕见的批判性距离。毕竟,谁会喜欢调查和确认自己的错误呢?一般来说,开发人员喜欢在自己的代码中尽可能少地发现错误。

  • 开发测试

开发者测试"(见第3.4.1节)的最大弱点是,每个测试自己代码的开发者总是以过于乐观的态度看待自己的工作。他极有可能忽略有意义的测试案例,或者因为他对编程比对测试更感兴趣,所以他的测试不够彻底。
对自己的错误视而不见

如果开发者误解了任务,设计了一个有根本缺陷的程序,那么他根本不会想到合适的测试用例,也不会发现这个缺陷。减少这种常见的 "对自己的错误视而不见 "的方法是结对工作,让每个开发人员测试对方的工作(见6.1节,模型1)。
另一方面,对自己的测试对象的内部知识可以成为一种优势,因为你不需要花时间去了解代码。由管理层来决定何时了解自己工作的优势超过对自己的错误视而不见所造成的劣势。这个决定是基于测试对象的重要性和如果失败所涉及的风险程度。
为了设计有意义的测试用例,测试人员必须了解测试对象的情况,这需要时间。另一方面,测试人员拥有开发人员必须学习的专业技能,以便有效地进行测试--这是一个学习过程,通常没有多余的时间。
开发人员需要测试技能,测试人员需要开发技能。

如果开发人员和测试人员都能掌握一些对方的技能,这对他们之间的合作和理解是有很大帮助的。开发人员应该总是知道一些测试的基本知识,测试人员应该总是有一些开发经验。

参考资料

2.5 总结

  • 测试术语只有松散的定义,类似的术语经常被用来表示不同的东西--这是经常发生误解的原因。这就是为什么术语的一致使用是认证测试员课程的一个重要部分。本书末尾的词汇表提供了所有最重要术语的概述。
  • 测试占据了项目开发资源的很大一部分。确切地说,需要多少测试工作取决于手头的项目类型。
  • 测试过程--从计划和准备步骤开始--需要尽早开始,以便在项目中产生最大的测试效益。
  • 始终遵循七个基本测试原则。
  • 认识和观察测试、质量保证和质量管理之间的联系和界限是很重要的。
  • 测试过程包括测试计划、监测和控制、分析、设计、实施、执行和完成。这些活动可以重叠,可以按顺序或平行进行。整个测试过程必须适应手头的项目。
  • 各个测试活动的结果之间的双向可追溯性,确保你可以对测试过程的结果做出有意义的陈述,并对对系统进行修改所需的努力做出合理的估计。可追溯性对于有效的测试监测和控制也是至关重要的。
  • 在一个组织内,所有影响测试的许多因素都必须被考虑。
    人们会犯错,但通常不愿意承认!这就是为什么心理问题在测试中发挥着重要作用!这就是为什么心理问题在整个测试过程中起着重要作用。
    测试人员和开发人员的心态是非常不同的,但两者都可以通过相互学习而受益。
内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/testing-/p/17384234.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!