可维护性测试指南 - 什么是可维护性测试?
维护的主要定义是保持或维持特定状态的过程。软件的可维护性由开发人员负责,他们定期修改软件以满足不断变化的客户需求并解决客户提出的问题。
软件维护需要增强软件的功能,以包含客户需要的新功能,修改代码以避免将来出现问题,修复代码中的缺陷或错误,并确保不存在安全漏洞。此外,软件维护通常包括发布更新,以提高适应性和有效性,并替换不受欢迎的功能。
软件维护在很大程度上受到软件和代码质量的影响。质量较低的软件需要更多的维护。对于低质量软件,增加新需求或扩展现有代码的工作量和成本要高得多。
随着可维护性的提高,软件维护的过程也会大大简化。可维护性测试可以帮助应用程序的设计更具有容错性,这反过来又意味着软件维护对错误修复的需求将大大降低;这只是说明可维护性测试必要性的一个例子,本指南中还有更多的例子。
为了让客户满意并保持软件产品的功能,进行可维护性测试是至关重要的。
软件维护的测量指标和类型
任何软件都可能经历四种不同类型的维护。这些不同形式的维护分别服务于特定的目标。
- 纠正性维护
无论经过多么广泛的测试,软件产品都可能存在缺陷,而这些缺陷会在没有太多警告的情况下显现出来。发现这些错误并进行修复所需的时间可以衡量软件的可维护性。
-
完善性维护
这种类型的维护主要是通过改进来优化软件。进行这些改进所需的工作量可以用来衡量软件产品的可维护性。在软件中引入新功能所花费的时间和精力可以与预定义的基线或其他以前完成的项目进行比较,以获得准确的评估。 -
适应性维护
除了因改进而产生的修改外,软件产品还经常需要因操作系统更新或程序所依赖的其他软件更新而进行更改。适应性维护包括为保持软件产品与不断变化的环境(如不断变化的硬件和操作系统)兼容而进行的调整。为实现更好的兼容性而引入这些变化所需的时间和精力可以作为衡量软件可维护性的另一个指标。 -
预防性维护
这是对软件进行的维护,目的是减少将来可能需要进行的维护。
对软件进行这些更改是为了先发制人地解决未来的问题,并使软件对可能出现的问题有更强的承受力。
如何衡量应用程序的可维护性?
衡量一个应用程序的可维护性有几个属性。应用程序的可变更性和在变更过程中的稳定性是两个可能的衡量标准。此外,还可以根据分析应用程序以查找错误的难易程度来衡量可维护性。
ISO是国际公认的标准,为系统和软件质量要求和评估(SQuaRE)提供了指南。ISO 25010定义了衡量软件质量的以下特征。
- 模块化
考察应用程序的模块化程度。它评估软件是否由不同的模块化组件组成,或者是否有非模块化的、可能相互依赖的组件。
- 重用性
该标准重点关注已有代码是否可以重新利用,以便在应用程序的其他地方提供类似功能。重复使用代码可以降低成本、提高生产率和整体质量。
- 可分析性:
意外软件缺陷被发现和修复的有效程度。该参数还可用于评估实施某项变更或软件升级的效果。
- 可修改性:
评估在不降低或损害最终产品质量的情况下,应用程序的可修改程度。
- 可测试性
可测试性是指在多大程度上可以为应用程序制定测试标准,以及是否可以通过运行上述测试来检验这些标准是否得到满足。
通过了解各种形式的软件维护和相应的属性来衡量应用程序的可维护性,可维护性测试可以准确地认识到成功和轻松地修复或更新软件的潜力。
可维护性是指更新、修改、重用和测试系统的能力。这对大多数系统都很重要,因为大多数系统在其生命周期内都会被多次更新、修改和测试。通常情况下,系统的各个部分甚至整个系统都会被用于新的和不同的场合。
为什么要对系统进行所有的更改?请记住,当我们讨论可靠性时,我们说过软件不会磨损,但会过时。我们需要新的扩展功能。我们还需要补丁和更新,以使系统运行得更好。我们必须适应新发布的环境,互操作系统也将更新,通常需要对我们的系统进行更新。
设计问题。概念问题。符合标准和指南(或不符合标准和指南)。我们有一个很好的方法来发现这些问题。这就是静态测试。从最初的需求到最新的补丁,可能没有更好的方法来确保系统的可维护性。在这种情况下,一个新工具、几个脚本测试或相当细心的测试人员并不能神奇地将猪耳朵变成丝绸钱包。
必须让管理层了解良好的可维护性所需要的投资。这必须被视为一项长期投资,因为大部分的回报都会在未来的道路上出现。而且,这也是最难出售的一种投资,因为它大多是无形的。如果我们很好地建立了一个可维护的系统,我们如何以有形的方式向管理层展示回报呢?
好吧,我们不会有那么多的补丁,但我们无法毫无疑问地证明这是投资的结果。我们的维护程序员会犯更少的错误,导致更少的回归错误,但我们不一定能指出我们没有犯的错误。
参考资料
- 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- https://www.browserstack.com/guide/maintainability-testing
- https://www.tmap.net/building-blocks/maintainability-testing
如何进行可维护性测试?
在实施可维护性测试时,并没有硬性的规则来定义需要遵循的流程。一个软件应用程序在发布之前和发布之后,预计会经过多次更新,以纠正错误、引入新功能、调整现有功能和改变非功能性软件特征。
因此,这种测试可能因具体情况而异,实施方法也可能不同。然而,一般来说,通过自动化测试工具,如Selenium或Percy进行可视化测试,可以极大地支持和加快可维护性测试。
测试选项可维护性测试可以使用静态或动态测试方法。作为软件开发过程的一部分,静态测试检查设计文档和源代码的组织、结构、复杂性和其他特性。
静态测试的一些示例如下
- 某些控制结构(如决策语句)的嵌套深度
- 循环复杂性
静态分析和审查是可维护性测试的适当方法,它们应该在设计文档可用时就开始,并在构建应用程序的整个过程中持续进行。
静态分析和评审是可维护性测试的合适方法,应该从设计文档开始,贯穿整个应用程序开发过程。可维护性可以在软件开发生命周期的早期进行评估,而不需要等待一个完成的和可运行的系统,因为可维护性已经融入到代码和每个单独代码组件的文档中。
动态软件测试是为了检查代码的动态特性并确定其功能。它提供了应用程序在使用中的行为的有价值的信息。
动态测量的一些示例包括
- 对更新或错误修复的持续时间进行计时。
- 系统在两次更改之间的稳定性。
动态可维护性测试的重点是为特定的应用程序制定文档化的维护流程,例如对软件进行更改或改进。为了确认规定的服务水平可以通过概述的流程来实现,需要使用各种维护情况作为测试用例。
当支持的基础设施非常复杂,并且可能有多个部门或组织参与支持程序时,这种类型的测试尤为重要。
可维护性测试最佳实践
-
在进行可维护性测试时,有必要制定一个可维护性因素清单,如系统的稳定性或代码的复杂性。
-
确保软件符合数据库、界面和开发过程的适当标准。例如,验证软件是否遵循优化算法和代码重用性等良好实践。
-
创建一个可维护性衡量标准来表示特定因素的可维护性成本和优势是很有帮助的。对于所评估的每个组件,都可以分配一种加权分数,以便进行排序,确定哪些方面需要最大的关注。这有助于制定行动计划,优先解决得分最高的因素。
-
确保软件符合前面讨论的五个可维护性属性: 模块化、可重用性、可分析性、可修改性和可测试性。
易分析性
软件产品被诊断出缺陷或故障原因的能力,或者被识别出需要修改的部分的能力。换句话说,需要花费多少精力才能诊断出系统中的缺陷,或确定需要修改的地方?
以下是可分析性差的四个常见原因,排名不分先后。
-
没有模块化
-
缺乏良好的文档。
-
标准和指南不完善,或者根本不存在。没有编程规范。
-
抽象程度过高
解决大多数问题的方法都是一样的。良好、可靠的标准和指南。随时通过静态测试来执行,尤其是在时间紧迫的情况下。没有借口。如果组织明确指出,可分析性差是一类重要的缺陷,是不能容忍的,那么往往就不会出现这个质量子特性的问题。
内部可分析性指标
- 活动记录
衡量系统状态记录的详尽程度。其计算方法是,计算按照规定写入活动日志的项目数,与根据需求应该写入的项目数进行比较。计算公式为X = A / B
其中,A是实际按照规定写入活动日志的项目数量(经审核确认),B是按照规范规定应写入日志的项目数量。该值越接近1,日志记录就越完整。
- 诊断功能的准备程度
衡量诊断功能提供的全面程度。诊断功能分析故障,并向用户提供输出或日志,解释故障原因。该指标是已实现的诊断功能与技术规范中要求的诊断功能数量的比率,使用相同的公式计算:X = A / B
A是已实施的诊断功能数量(审查中发现),B是技术规范中要求的数量。该指标也可用于衡量系统的故障分析能力和因果分析能力。
外部可分析性指标
组织可能希望跟踪的外部可维护性度量。在测试或维护过程中,当软件被维护或修改时,这些指标有助于测量维护者、用户或系统的行为等属性。
- 审计跟踪能力
衡量用户(或维护者)识别导致故障的具体操作的难易程度。ISO 9126-2在解释如何记录这一指标时有些抽象:它说要观察试图解决故障的用户或维护者。这似乎与该指标的计算方法相悖,即使用公式X = A / B
其中,A是运行期间实际记录的数据项数量,B是为充分监控运行期间软件状态而应记录的数据项数量。与本标准中的许多其他指标一样,企业必须自行定义B的确切值。有多少可能发生的不同错误情况应被记录?X的值越接近1,意味着记录的所需数据越多。组织必须将此视为一种权衡;我们希望记录的越多,就需要编写更多的代码来监控执行、评估发生了什么并记录下来。
- 诊断功能支持
衡量诊断功能支持因果分析的能力。换句话说,用户或维护人员能否识别导致故障的特定功能?与上一个指标一样,应用方法仅指观察用户或维护人员试图使用诊断功能解决故障的行为。计算公式为X = A / B
其中,A是使用诊断功能成功分析的故障数量,B是登记的故障总数。越接近1越好。
- 故障分析能力
衡量用户或维护人员识别导致故障的具体操作的能力。要计算该指标,请使用公式X = 1 - A / B
其中,A是仍未找到原因的故障数量,B是登记的故障总数。请注意,这实际上是上一个指标诊断功能支持的反面。这个指标衡量的是我们无法诊断的故障数量,而上一个指标衡量的是我们诊断出的故障数量。越接近1.0越好。
- 故障分析效率
衡量用户或维护人员分析故障原因的效率。这实质上是对解决系统故障所用平均时间的衡量,计算公式为X = Sum(T) / N。
其中,T是每次解决故障所需的时间,N是已解决问题的数量。该指标的标准中有两个有趣的说明。ISO 9126-2指出,只有成功解决的故障才应包括在此测量中;但是,它接着指出,未解决的故障也应进行测量并一并提交。该标准还指出,在计算这一指标时,可以使用人时而非简单的小时数,这样就可以衡量出努力程度而非简单的经过时间。
- 状态监测能力
衡量在系统实际运行过程中导致故障的操作是否容易获得监控数据。该指标的计算公式为X = 1 - A / B
其中,A是用户或维护人员试图获取监控数据但失败的案例数,B是他们在运行过程中试图获取监控数据的案例数。越接近 1 越好,这意味着他们在尝试获取监控数据时越成功。
可变更性(易修改性 Changeability | Modifiability)
软件产品能够实现特定修改的能力。
几乎所有影响可变更性的因素都是设计和实施实践。
基于设计的问题包括耦合和内聚。耦合和内聚是指系统如何被分割成模块。高耦合度和低内聚性对良好的软件设计是有害的。
耦合是指模块在执行过程中相互依赖内部操作的程度。高耦合意味着模块之间存在大量的依赖关系和共享代码。另一种可能是,一个模块依赖于另一个模块做某事的方式。如果改变这种依赖关系,就会破坏第一个模块。当允许高耦合时,对单个模块进行修改变得非常困难;这里的修改通常意味着那里和那里的更多修改。低耦合是可取的;每个模块都有自己的任务,并且基本上是独立完成的。
有许多不同类型的耦合:
- 内容耦合
当一个模块访问另一个模块的本地数据时。
- 共用耦合:两个或多个模块共享全局数据。
- 外部耦合:两个或多个模块共享一个外部接口或设备。
- 控制耦合:一个模块告诉另一个模块做什么。
- 数据结构耦合:多个模块共享一个数据结构,每个模块只使用其中的一部分。
- 数据耦合:数据从一个模块传递到另一个模块--通常通过参数。
- 消息耦合:模块之间互不依赖;模块之间传递消息而不传递数据。
- 无耦合:模块之间完全不通信。
通常需要一些耦合;模块通常必须能够通信。一般来说,消息耦合或数据耦合是最佳选择。
另一方面,内聚描述了模块职责的集中程度。一般来说,模块应该只做一件事,而且要做得很好。内聚性低的指标包括:模块中的许多函数或方法做不同的事情,而这些事情是不相关的,或者它们处理的是完全不同的数据集。
一般来说,低耦合度和高内聚度是相辅相成的,是可变更性良好的标志。高耦合度和低内聚度通常是设计流程不完善的表现,也是可变更性差的标志。
由不恰当的实现方法引起的可变更性问题涉及到我们在编程课上被告知不能做的许多事情。
使用全局变量是最大的问题之一;它导致了高度的耦合,一个模块中变量的改变可能会对其他模块产生一系列的副作用。
将变量值硬编码到模块中应该被视为一个严重的潜在错误。对于开发人员来说,命名常量是一种更好的编写代码的方式;当他们决定改变值时,所有的实例都会被一次性改变。当使用硬编码值(有些人称之为神奇数字)时,总会有一些被改变,而另一些不会。
对硬件进行硬编码设计也是一个问题。为了提高速度,一些开发人员喜欢按照他们所编写的平台的硬件进行编程。这可能意味着使用操作系统、硬件平台或正在使用的设备的实现细节。当然,当时间流逝,硬件、操作系统和/或设备发生变化时,软件就会出现问题。
系统越复杂,可变性就越差。与往常一样,有时我们需要对复杂性进行权衡。
我们前面提到的Jamie参与的项目,即重写一个中端计算机操作系统,就是软件工程做得很好的一个例子!每个开发人员和大多数测试人员都接受了为期数周的全职面向对象开发和设计培训。他们将2500万行的PL/MP(一种优雅的过程语言)代码转换为C++,这不是一个补丁,而是一次彻底的重写。他们花了大量时间制定每个开发人员都必须遵守的标准和指南。他们在静态测试方面进行了大量投资,并对每个人进行了培训。
低耦合和高内聚是当时的流行语。也许 "流行语 "是不正确的;他们真正相信自己正在做的事情。可维护性是规则。
他们的经验法则是将任何方法、函数或代码限制在打印出来的一页纸上。也许20到25行代码。他们使用良好的面向对象规则,包括类、继承和数据隐藏。他们在模块之间使用消息传递来避免任何全局变量。他们让人编写类库,并对其进行测试,从而真正实现了重复使用。
因此,您可能会认为一切都非常顺利。最终的结果是出色的,但一路上也有不少磕磕绊绊。他们有一个操作系统必须提供的特殊功能;他们估计,使用新的处理器,他们必须在7000个CPU周期内完成任务。重写后,他们发现执行该操作需要超过99,000个CPU周期。他们的误差非常大。而且,由于这个动作每分钟可能会发生数千次,他们的设计需要完全重新考虑。事实上,低耦合、高内聚、继承和数据隐藏都有各自的代价。
每个设计决策都需要权衡利弊。对于许多系统来说,好的设计和技术值得我们为之花费每一分钱。但是,当执行速度是最重要的时候,这些技术往往不能很好地发挥作用。为了使系统正常运行,他们不得不抛弃所有的规则。在这个模块中,他们重新使用了庞大的函数、直接的过程代码、全局变量、低内聚性和高耦合性。而且,他们做得足够快。然而,正如您所期望的那样,它非常容易出问题;花了相当长的时间才稳定下来。
糟糕的文档会对可变更性产生不利影响。如果维护程序员必须猜测如何进行修改,推断原始程序员的想法,那么可变更性就会受到很大影响。文档包括内部文档(代码中的注释,通过良好的命名方式实现代码的自文档化等)和外部文档,包括高层和低层的设计文档。
内部可变更性度量
- 变更可记录性
对规范和程序模块的变更如何完整记录的度量。ISO 9126-3将其定义为代码或其他文档中的变更注释。该指标的计算公式为X = A / B
其中,A是有注释的变更数量(经评审确认),B是变更总数。该值应为0 <= X <= 1,越接近1越好。接近 0 的值表示变更控制不佳。
- 外部可变更性指标
外部可变更性度量有助于衡量当您试图对系统实施变更时所需要的努力。
- 变更周期效率
衡量在可接受的时间内解决用户问题的可能性。该指标通过监控用户与维护者之间的交互,并记录从最初的用户请求到问题解决之间的时间来衡量。该指标的计算公式为Tav = Sum(Tu) / N
其中,Tav为平均时间,Tu为用户从发送问题报告到收到修订版之间的时间,N为发送的修订版数量。Tav越短越好;但是,大量的修订可能会对组织产生反作用,因此应取得平衡。
- 变更执行时间
用于衡量维护人员为解决故障而更改软件的难易程度。计算公式为Tav = Sum(Tm) / N
其中,Tav是平均时间,Tm是检测到故障到找到故障原因之间的时间,N是登记和删除的故障数量。如前所述,有两点需要注意。应排除尚未发现的故障,并且可以使用努力(人-小时)来代替经过时间。时间越短越好。
- 修改复杂性
衡量维护者为解决问题而修改软件的难易程度。计算公式为T = Sum(A / B) / N
其中,T是修复故障的平均时间,A是更改特定故障所花费的工作时间,B是更改的大小,N是更改的次数。变更的大小可以是变更的代码行数、变更的需求数、变更的文档页数等。这个时间越短越好。显然,如果变更的次数过多,企业就应该关注。
- 软件变更控制能力
衡量用户识别软件修订版本的难易程度。这也被列为维护者如何轻松地更改系统以解决问题。其测量公式为X = A / B
其中,A是实际写入变更日志的条目数,B是计划的变更日志条目数,这样我们就可以跟踪软件的变更。越接近1越好,但如果变更很少,该值将趋向于0。
稳定性(Stability,并入Modifiability)
注意ISO25010没有此项。稳定性多和可靠性同义。
系统避免软件修改带来意外影响的能力。当我们对系统进行修改后,会产生多少缺陷?
这个子特性本质上是我们在可变更性中处理的所有问题的副作用。内聚度越低,耦合度越高,编程风格和文档越差,系统的稳定性就越低。
此外,我们还需要考虑需求的质量。如果需求定义明确、理解透彻、管理得当,那么系统往往会更加稳定。如果需求不断变化,并且没有被很好地记录和理解,那么系统的稳定性就会大打折扣。
系统时序对稳定性很重要。在实时系统中,或者当定时非常重要时,变化往往会使定时链发生偏移,从而在其它地方造成故障。
内部稳定性指标
稳定性指标帮助我们预测系统在修改后的稳定性。
- 变更影响
系统修改后不良反应发生频率的度量。该指标的计算公式为:将系统修改后发生的不利影响次数与实际修改次数进行比较X = 1 - A / B
其中,A为不利影响的数量,B为所做修改的数量。越接近1越好。请注意,由于马虎的变更管理方式可能会带来多种不利影响,因此该指标实际上可能为负值。例如,假设进行了一次变更,但出现了三次不良反应。使用该公式计算如下:X = 1 - 3/1 ==> -2.
- 修改影响定位
衡量修改对系统的影响程度。该值通过计算受修改影响的变量数量,并将其与产品中的变量总数进行比较,计算公式为X = A / B
其中,A为审查确认的受影响变量数量,B为变量总数。受影响变量的定义是代码行或计算机指令中被更改的任何变量。该值越接近零,说明修改的影响可能越小。
外部稳定性指标
- 修改成功率: 衡量用户在维护后操作软件系统而不会再出现故障的程度。有两个公式可用于衡量该指标:
X = Na / Ta
Y = {(Na / Ta) / (Nb / Tb)}
Na是软件更改后用户遇到故障的次数,Nb是软件更改前用户遇到故障的次数,Ta是软件更改后的运行时间(规定的观察时间),Tb是软件更改前的时间(规定的观察时间)。越小越好,越接近0越好。从本质上讲,X 和 Y 代表软件更改后遇到故障的频率。指定的观察时间用于使指标正常化,这样我们就可以更好地比较不同版本的指标。此外,ISO 9126-2还建议,组织可能希望区分同一模块/功能修复后出现的故障和其他模块/功能出现的故障。
- 修改对本地化的影响
这也是衡量用户在维护后能够在不发生进一步故障的情况下操作系统的程度。计算公式为X = A / N
其中,A 是系统修改后(在特定时期内)出现的故障数,N 是解决的故障数。该标准建议跟踪故障的 连锁情况;也就是说,组织应区分因先前故障而归因于变更的故障和似乎与变更无关的故障。越小越好,越接近零越好。
可测试性
可测试性是指软件产品在发生变更后的验证能力。这当然应该是所有技术测试分析师关注的问题。
许多问题都会对系统的可测试性提出挑战。
我们最喜欢的问题之一就是文档。代码中缺乏注释和糟糕的命名习惯,这使得理解代码到底应该做什么变得更加困难。
实施独立的测试团队可能会导致无意的(甚至有时是有意的)沟通中断。在处理可测试性问题时,测试团队和开发团队之间的良好沟通非常重要。
某些编程风格会使代码更难测试。例如,面向对象设计的主要目标之一就是数据隐藏。当然,数据隐藏也会使测试是否通过变得非常困难。多层次的继承使其变得更加困难;您可能不知道事情发生的确切位置,也不知道哪个类(对象)真正负责要采取的行动。
代码中缺乏工具导致可测试性问题。许多系统都具有自我诊断的能力;编写了额外的代码来确保任务正确完成,并记录发生的问题。不幸的是,这些工具通常被视为花哨的东西,而不是必需的。
最后一点,数据问题本身也会导致可测试性问题。在这种情况下,更好的安全性和良好的加密可能会降低系统的可测试性。如果无法找到、测量或理解数据,系统就更难测试。与软件中的许多情况一样,必须做出明智的权衡。
内部可测试性度量
内部可测试性指标衡量测试修改后系统所需的预期工作量。
- 内置测试功能的完整性
衡量内置测试功能的完整性。计算方法是:计算已实现的内置测试功能的数量,并与规范要求的数量进行比较。计算公式为X = A / B
其中,A是已实施的内置测试功能的数量(经审核确认),B是技术规范要求的数量。越接近1,越完整。
- 可测试性的自主性
衡量软件系统可独立测试的程度。该指标的计算方法是:计算使用存根或驱动程序模拟的其他系统的依赖项数量,并将其与其他系统的依赖项总数进行比较。与许多其他指标一样,计算公式为X = A / B
其中,A是使用存根或驱动程序模拟的依赖关系数,B是其他系统的依赖关系总数。越接近1越好。数值为1意味着可以模拟所有其他依赖系统,因此软件(基本上)可以自行测试。
- 测试进度可观察性
测试过程中内置测试结果的完整显示程度。计算公式为X = A / B
其中,A是审查中确认的已执行检查点的数量,B是规范中要求的数量。越接近1越好。
外部可测试性度量
可测试性度量衡量测试修改系统所需的工作量。
- 内置测试功能的可用性
衡量用户或维护者在没有额外的测试设施准备的情况下对系统进行操作测试的难易程度。该指标的计算公式为X = A / B
其中A是维护者可以使用内置测试功能的案例数,B是测试机会数。越接近1越好。
- 重新测试效率
衡量用户或维护者执行操作测试并确定软件是否准备好发布的难易程度。该指标是一个平均值,计算公式为
X = Sum(T) / N
其中,T是在故障解决后确保系统已做好发布准备所花费的时间,N是已解决故障的数量。从本质上讲,这是故障解决后的平均重新测试时间。请注意,未解决的故障不包括在此测量中。越小越好。
- 测试重启性
衡量用户或维护人员在维护后使用检查点执行操作测试的难易程度。计算公式为X = A / B
其中,A是维护者可以在所需位置暂停并重新启动正在执行的测试用例的测试用例数,B是正在执行的测试用例被暂停的测试用例数。越接近 1 越好。
符合性
内部符合性指标
可维护性合规性是对系统在多大程度上符合适用法规、标准和惯例的一种度量。已实施的合规项目(基于审查)与规范中要求合规的项目之间的比率使用以下公式计算X = A / B
其中,A是与可维护性合规性相关的正确执行项目,B是要求的数量。越接近 1,系统的符合性越高。
外部符合性指标
可维护性合规性度量可衡量系统在多大程度上遵守了各种标准、惯例和规定。合规性的测量公式为X = 1 - A / B
其中,A是测试期间未实施的可维护性符合性项目的数量,B是已定义的可维护性符合性项目的总数。越接近 1 越好。
上一篇: 软件测试方法有哪些分类?
下一篇: 20 个非常棒的网站可用性测试工具
推荐阅读
-
测试运维】Web 自动化全知识点笔记 编号:什么是 Web 自动化测试(已分享,附代码)
-
epoll简介及触发模式(accept、read、send)-epoll的简单介绍 epoll在LT和ET模式下的读写方式 一、epoll的接口非常简单,一共就三个函数:1. int epoll_create(int size);创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close关闭,否则可能导致fd被耗尽。2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);epoll的事件注册函数,它不同与select是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create的返回值,第二个参数表示动作,用三个宏来表示:EPOLL_CTL_ADD:注册新的fd到epfd中;EPOLL_CTL_MOD:修改已经注册的fd的监听事件;EPOLL_CTL_DEL:从epfd中删除一个fd;第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:struct epoll_event { __uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */};events可以是以下几个宏的集合:EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭); EPOLLIN事件:EPOLLIN事件则只有当对端有数据写入时才会触发,所以触发一次后需要不断读取所有数据直到读完EAGAIN为止。否则剩下的数据只有在下次对端有写入时才能一起取出来了。现在明白为什么说epoll必须要求异步socket了吧?如果同步socket,而且要求读完所有数据,那么最终就会在堵死在阻塞里。 EPOLLOUT:表示对应的文件描述符可以写; EPOLLOUT事件:EPOLLOUT事件只有在连接时触发一次,表示可写,其他时候想要触发,那要先准备好下面条件:1.某次write,写满了发送缓冲区,返回错误码为EAGAIN。2.对端读取了一些数据,又重新可写了,此时会触发EPOLLOUT。简单地说:EPOLLOUT事件只有在不可写到可写的转变时刻,才会触发一次,所以叫边缘触发,这叫法没错的!其实,如果真的想强制触发一次,也是有办法的,直接调用epoll_ctl重新设置一下event就可以了,event跟原来的设置一模一样都行(但必须包含EPOLLOUT),关键是重新设置,就会马上触发一次EPOLLOUT事件。1. 缓冲区由满变空.2.同时注册EPOLLIN | EPOLLOUT事件,也会触发一次EPOLLOUT事件这个两个也会触发EPOLLOUT事件 EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);EPOLLERR:表示对应的文件描述符发生错误;EPOLLHUP:表示对应的文件描述符被挂断;EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);等待事件的产生,类似于select调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。-------------------------------------------------------------------------------------------- 从man手册中,得到ET和LT的具体描述如下EPOLL事件有两种模型:Edge Triggered (ET)Level Triggered (LT)假如有这样一个例子:1. 我们已经把一个用来从管道中读取数据的文件句柄(RFD)添加到epoll描述符2. 这个时候从管道的另一端被写入了2KB的数据3. 调用epoll_wait(2),并且它会返回RFD,说明它已经准备好读取操作4. 然后我们读取了1KB的数据5. 调用epoll_wait(2)......Edge Triggered 工作模式:如果我们在第1步将RFD添加到epoll描述符的时候使用了EPOLLET标志,那么在第5步调用epoll_wait(2)之后将有可能会挂起,因为剩余的数据还存在于文件的输入缓冲区内,而且数据发出端还在等待一个针对已经发出数据的反馈信息。只有在监视的文件句柄上发生了某个事件的时候 ET 工作模式才会汇报事件。因此在第5步的时候,调用者可能会放弃等待仍在存在于文件输入缓冲区内的剩余数据。在上面的例子中,会有一个事件产生在RFD句柄上,因为在第2步执行了一个写操作,然后,事件将会在第3步被销毁。因为第4步的读取操作没有读空文件输入缓冲区内的数据,因此我们在第5步调用 epoll_wait(2)完成后,是否挂起是不确定的。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。最好以下面的方式调用ET模式的epoll接口,在后面会介绍避免可能的缺陷。 i 基于非阻塞文件句柄 ii 只有当read(2)或者write(2)返回EAGAIN时才需要挂起,等待。但这并不是说每次read时都需要循环读,直到读到产生一个EAGAIN才认为此次事件处理完成,当read返回的读到的数据长度小于请求的数据长度时,就可以确定此时缓冲中已没有数据了,也就可以认为此事读事件已处理完成。Level Triggered 工作模式相反的,以LT方式调用epoll接口的时候,它就相当于一个速度比较快的poll(2),并且无论后面的数据是否被使用,因此他们具有同样的职能。因为即使使用ET模式的epoll,在收到多个chunk的数据的时候仍然会产生多个事件。调用者可以设定EPOLLONESHOT标志,在 epoll_wait(2)收到事件后epoll会与事件关联的文件句柄从epoll描述符中禁止掉。因此当EPOLLONESHOT设定后,使用带有 EPOLL_CTL_MOD标志的epoll_ctl(2)处理文件句柄就成为调用者必须作的事情。然后详细解释ET, LT:LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表.ET(edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认(这句话不理解)。在许多测试中我们会看到如果没有大量的idle -connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当我们遇到大量的idle- connection(例如WAN环境中存在大量的慢速连接),就会发现epoll的效率大大高于select/poll。(未测试)另外,当使用epoll的ET模型来工作时,当产生了一个EPOLLIN事件后,读数据的时候需要考虑的是当recv返回的大小如果等于请求的大小,那么很有可能是缓冲区还有数据未读完,也意味着该次事件还没有处理完,所以还需要再次读取: 这里只是说明思路(参考《UNIX网络编程》) while(rs) {buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);if(buflen < 0){// 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读// 在这里就当作是该次事件已处理处.if(errno == EAGAIN)break; else return; }else if(buflen == 0) { // 这里表示对端的socket已正常关闭. } if(buflen == sizeof(buf) rs = 1; // 需要再次读取 else rs = 0; } 还有,假如发送端流量大于接收端的流量(意思是epoll所在的程序读比转发的socket要快),由于是非阻塞的socket,那么send函数虽然返回,但实际缓冲区的数据并未真正发给接收端,这样不断的读和发,当缓冲区满后会产生EAGAIN错误(参考man send),同时,不理会这次请求发送的数据.所以,需要封装socket_send的函数用来处理这种情况,该函数会尽量将数据写完再返回,返回-1表示出错。在socket_send内部,当写缓冲已满(send返回-1,且errno为EAGAIN),那么会等待后再重试.这种方式并不很完美,在理论上可能会长时间的阻塞在socket_send内部,但暂没有更好的办法. ssize_t socket_send(int sockfd, const char* buffer, size_t buflen) { ssize_t tmp; size_t total = buflen; const char *p = buffer; while(1) { tmp = send(sockfd, p, total, 0); if(tmp < 0) { // 当send收到信号时,可以继续写,但这里返回-1. if(errno == EINTR) return -1; // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满, // 在这里做延时后再重试. if(errno == EAGAIN) { usleep(1000); continue; } return -1; } if((size_t)tmp == total) return buflen; total -= tmp; p += tmp; } return tmp; } 二、epoll在LT和ET模式下的读写方式 在一个非阻塞的socket上调用read/write函数, 返回EAGAIN或者EWOULDBLOCK(注: EAGAIN就是EWOULDBLOCK) 从字面上看, 意思是: * EAGAIN: 再试一次 * EWOULDBLOCK: 如果这是一个阻塞socket, 操作将被block * perror输出: Resource temporarily unavailable 总结: 这个错误表示资源暂时不够, 可能read时, 读缓冲区没有数据, 或者, write时,写缓冲区满了 。 遇到这种情况, 如果是阻塞socket, read/write就要阻塞掉。 而如果是非阻塞socket, read/write立即返回-1, 同 时errno设置为EAGAIN. 所以, 对于阻塞socket, read/write返回-1代表网络出错了. 但对于非阻塞socket, read/write返回-1不一定网络真的出错了. 可能是Resource temporarily unavailable. 这时你应该再试, 直到Resource available. 综上, 对于non-blocking的socket, 正确的读写操作为: 读: 忽略掉errno = EAGAIN的错误, 下次继续读 写: 忽略掉errno = EAGAIN的错误, 下次继续写 对于select和epoll的LT模式, 这种读写方式是没有问题的. 但对于epoll的ET模式, 这种方式还有漏洞. epoll的两种模式 LT 和 ET
-
究竟什么是单元测试?应该如何进行?
-
[一文读懂】单元测试到底是什么?应该怎么做?-首先,什么是单元测试?
-
什么是单元测试,如何编写单元测试?
-
什么是可用性测试?有效性(Effectiveness)-- 用户完成特定任务和实现特定目标的正确性和完整性程度;效率(Efficiency)-- 用户完成任务的正确性和完整性程度与所用资源(如时间)之比;满意度(Satisfaction)-- 用户在使用产品时的主观满意度和接受程度。 2.如何获得可用性? 可以参考以下原则:Gould、Boies 和 Lewis(1991 年)为以用户为中心的设计定义了 4 个重要原则: 早期以用户为中心:设计者应在设计过程的早期就努力了解用户的需求。 综合设计:设计的所有方面都应同步发展,而不是按顺序进行。使产品的内部设计始终与用户界面的需求保持一致。 早期和持续测试:当今唯一可行的软件测试方法是经验主义方法,即如果实际用户认为设计可行,该设计就是可行的。通过在整个开发过程中引入可用性测试,用户就有机会在产品推出之前对设计提出反馈意见。 迭代设计:大问题往往掩盖了小问题的存在。设计人员和开发人员应在整个测试过程中对设计进行迭代。 3...什么是可用性测试? 可用性测试是根据可用性标准对图形用户界面进行的系统评估。 可用性测试是衡量用户与系统(网站、软件应用程序、移动技术或任何用户操作设备)交互时的体验质量。4.如何进行可用性测试? l 实验室实验
-
什么是可用性测试?
-
什么是可用性测试?
-
什么是可用性测试
-
什么是软件可靠性测试?传统的软件可靠性测试程序和类型有哪些?