第一章 引论

  • 采用先进的开发方式和较完善的开发流程,可以减少错误的引入,但不可能完全杜绝软件中的错误。
  • 软件测试伴随着软件开发,以检验每一个阶段性的成果是否符合质量要求和达到预先定义的目标,尽可能早地发现错误并及时地修正。
  • 为什么要进行软件测试?答案很简单,就是为了保证软件质量。
  • 软件测试,就好比制造工厂的质量检验,是对软件产品和阶段性工作成果进行质量检验,力求发现其中的各种缺陷,并督促缺陷得到修正,从而控制软件产品的质量。
  • Bill Hetzel在1983年,软件测试就是一系列活动,这些活动是为了评估一个程序或软件系统的特性能力,并确定其是否达到了预期结果。
  • Glenford J. Myers在1979 测试是为了发现错误而执行一个程序或者系统的过程。
  • Glenford J. Myers的软件测试定义,虽然受到业界的普遍认同,但也存在一些问题,例如:
    1. 如果只强调测试的目的是寻找错误,就可能使测试人员容易忽视软件产品的某些基本需求或客户的实际需求,测试活动可能会存在一定的随意性和盲目性。
    2. 如果只强调测试的目的是寻找错误,使开发人员容易产生一个错误的印象,认为测试人员的工作就是挑毛病的。
  • IEEE1983 of IEEE Standard 729 中对软件测试下了一个标准的定义:使用人工或自动手段来运行或测定某个系统的过程,其目的在于检验它是否满足规定的需求或是弄清预期结果与实际结果之间的差别。
  • 在著名的软件瀑布模型中,软件测试是处在“编程”的下游、在“软件维护”的上游,
  • 在著名的软件瀑布模型中,强调测试仅仅是对程序的检验。
  • 现在人们普遍认为软件测试贯穿着整个软件生命周期。
  • V模型,说明软件测试活动和项目同时启动,软件测试的工作很早就开始了,避免了瀑布模型所带来的误区——软件测试是在代码完成之后进行。(画出软件开发和测试的v模型)
  • 任何形式的产品都是过程执行得到的结果,因此对过程进行管理与控制是提高产品质量的一个重要途径。
  • 软件质量保证(Software Quality Assurance,SQA)活动是通过对软件产品有计划地进行评审和审计来验证软件是否合乎标准的系统工程,通过协调、审查和跟踪以获取有用信息,形成分析结果以指导软件过程。

#第二章 软件测试的基本概念

  • 1983年ANSI/IEEE STD729给出了软件质量定义——软件产品满足规定的和隐含的与需求能力有关的全部特征和特性,它包括:
    1. 软件产品质量满足用户要求的程度;
    2. 软件各种属性的组合程度;
    3. 用户对软件产品的综合反映程度;
    4. 软件在使用过程中满足用户的程度;
  • 根据标准ISO/IEC TR 9126(2003)或新的ISO/IEC 25000(2010)系列标准,软件质量分为内部质量、外部质量、使用质量
  • 在IEEE Standard 729(1983)中对软件缺陷给出了一个标准定义:
    1. 从产品内部看,软件缺陷是软件产品开发或维护过程中所存在的错误、毛病等各种问题。
    2. 从外部看,软件缺陷是系统所需要实现的某种功能的失效或违背。
  • 软件缺陷就是软件产品中所存在的问题,最终表现为用户所需的功能没有完全实现,没有满足用户的需求。
  • 软件缺陷表现的形式是各种各样的,不仅体现在功能的失效方面,还体现在其他方面,例如:
    1. 运行出错,包括运行中断、系统崩溃、界面混乱。
    2. 数据计算错误、导致结果不正确。
    3. 功能、特性没有实现或部分实现。
    4. 在某种特定条件下没能给出正确或准确的结果。
    5. 计算的结果没有满足所需要的精度。
    6. 用户界面不美观,如文字显示不对齐、字体大小不一致等。
    7. 需求规格说明书的问题,如漏掉某个需求、表达不清楚或前后矛盾等。
    8. 设计不合理,存在缺陷。例如,计算机游戏只能用键盘玩而不能用鼠标玩。
    9. 实际结果和预期结果不一致。
    10. 用户不能接受的其他问题,如存取时间过长、操作不方便等。
  • 规格说明书是软件缺陷出现最多的地方。
  • 缺陷发现或解决得越迟,成本就越高。
  • 软件评审的形式有互为评审、走查和会议评审。
  • 测试计划是为了高效地、高质量地完成测试任务而做的准备工作,包括对工作量的估算、测试资源和进度安排、测试风险评估、测试策略制定等工作。
  • 测试计划书的主要内容集中在下列几个方面:
    1. 目标和范围:包括产品特性、质量目标、各阶段的测试对象、目标、范围和限制。
    2. 项目估算:根据历史数据和采用恰当的评估技术,对测试工作量、所需资源(人力、时间、软硬件环境)做出合理的估算。
    3. 风险计划:对测试可能存在的风险进行分析、识别,以及对风险的回避、监控和管理。
    4. 进度安排:分解项目工作结构,并采用时限图、甘特图等方法制定时间/资源表。
    5. 资源配置:人员、硬件和软件等资源的组织和分配包含每一个阶段和每一个任务所需的资源。
    6. 跟踪和控制机制:包括质量保证和控制、变化管理和控制等,明确如何准备去做一个问题报告以及如何去界定一个问题的性质,问题报告包括问题的发现者和修改者,问题发生的频率,是用什么样的测试用例测出该问题的,以及明确问题产生时的测试环境。
  • 测试用例是为了特定的测试目的(如考察特定程序路径或验证某个产品特性)而设计的测试条件、测试数据及与之相关的测试规程的一个特定的使用实例或场景。
  • 测试用例的主要作用有一下几方面:
    1. 测试用例是测试人员在测试过程中的重要参考依据。
    2. 测试用例可以帮助实施有效的测试,所有被执行的测试都是有意义的,不要执行毫无意义的测试操作。
    3. 良好的测试用例不断地被重复使用,使得测试过程事半功倍。
    4. 测试用例是一个知识积累的过程。
  • 专职测试人员的主要责任应该是:
    1. 尽早地、尽可能地发现软件程序、系统或产品中的问题,并督促开发人员尽快地解决程序中的缺陷;
    2. 能够全面、客观地评估软件质量,及时提供项目的当前质量状态;
    3. 持续地提供软件产品质量的反馈,暴露产品质量风险,引导团队关注质量;
    4. 对质量工作的质量和效率负责,成为测试工作的负责人;
    5. 成为测试专家,不断改进测试方法,提高测试效率,并能够指导开发人员或其他人员做好测试;
    6. 对缺陷进行根本原因分析,抽象出缺陷模式,帮助团队做好缺陷预防;
    7. 帮助团队建立质量保证体系,如督促编程规范的建立好实施。

第三章 软件测试方法

  • Pair-wise方法,也称为“成对组合测试”、“两两组合测试”,即将众多因素的值两两组合起来而大大减少测试用例组合。
  • 导致程序员犯错的因素很多,有程序员本身的编程水平、习惯以及所属团队软件工程管理水平等,编程语言及其相关类库的有些难以理解的特性也是一个比较重要的原因。
  • 大量的测试数据统计分析可以发现有些软件缺陷是具有共性的。常见的软件缺陷模式,
    1. 故障模式
    2. 安全漏洞模式
    3. 差性能模式
    4. 并发缺陷模式
    5. 不良习惯模式
    6. 代码国际化模式
    7. 易诱骗代码模式
  • 测试过程从源代码输入开始,经历预编译、词法分析、语法分析与语义处理、抽象语法树生成、控制流图生成和IP(ILLegal Pattern,非法模式)扫描等几个步骤,最后自动生成IP报表
  • 基于模式的测试,往往不是直接针对被测系统进行,而是根据算法、规则,针对源代码进行检测。
  • 基于模式的软件测试技术不能替代已有的其他测试技术,而是对其他测试技术一个有力的补充。
  • 一个程序的功能通常由静态说明和动态说明组成,动态说明描述了输入数据的次序或者转换的次序;静态说明描述了输入条件和输出条件之间的对应关系。对于比较复杂的程序,由于大量的组合情况存在,如果仅使用静态说明来组织测试往往是不够的,必须通过动态说明来补充测试。
  • 功能图法就是使用功能图形式化地表示程序的功能说明,并机械地生成功能图的测试用例。功能图模式由状态迁移图和逻辑功能模型组成。
    1. 状态迁移图用于表示输入数据序列以及相应的输出数据,由输入和当前的状态决定输出数据和后续状态。
    2. 逻辑功能模型用于表示在状态输入条件和输出条件之间的对应关系。逻辑功能模型只适用于描述静态说明,输出数据仅由输入数据决定。
  • 模糊测试方法,简单地说,就是通过一个自动产生数据的模板或框架(称为模糊器)来构造或自动产生大量的、具有一定随机性的数据作为系统的输入,从而检验系统在各种数据情况下是否会出现问题。
  • 形式化规范说明语言,一般由以下三个主要的成分构成。
    1. 语法,定义用于表示规约的特定符号;
    2. 语义,帮助定义用于描述系统的对象及其属性;
    3. 一组关系,定义如何确定某个对象是否满足规约的规则。
  • 形式化验证,就是根据某些形式规范或属性,使用数学方法(形式逻辑方法)证明其正确性或非正确性。
  • 软件测试无法证明系统不存在缺陷,也不能证明它符合一定的属性。只有形式化验证过程可以证明一个系统不存在某个缺陷或证明一个系统符合某个属性。但是,还无法证明某个系统没有缺陷,这是因为不能形式化地定义“没有缺陷”。所以,我们能做的就是证明一个系统不存在可以想得到的缺陷,以及验证满足系统质量要求的属性。
  • 给定程序,根据语句覆盖、判断覆盖、条件覆盖和路径覆盖设计测试样例;
  • 给定程序或输入数据说明,根据等价类划分或边界值分析设计测试样例。

第四章 软件测试流程和规范

  • W模型增加了软件各开发阶段中应同步进行的验证和确认活动。
  • 测试过程和开发过程都贯穿软件过程的整个生命周期,她们是相辅相成、相互依赖的关系,概况起来有以下三个关键点。
    1. 测试过程和开发过程是同时开始的,同时结束的,两者保持同步的关系。
    2. 测试过程是对开发过程中阶段性成果和最终的产品进行验证的过程,所以两者相互依赖。前期,测试过程更多地依赖于开发过程;后期,开发过程更多地依赖于测试过程。
    3. 测试过程中的工作重点和开发工作的重点,可能是不一样的。两者有各自的特点。不论在资源管理方面,还是在风险管理方面,两者都存在着差异。
  • TMap所定义的测试生命周期由计划和控制、基础设施、准备、说明、执行和完成等阶段组成。这个过程目前也被ISTQB(国际软件测试资质认证委员会)所采用,成为测试过程的标准。
  • 测试驱动开发的思想是敏捷测试的核心,或者说,单元测试是敏捷测试的基础,在敏捷测试中,开发人员承担更多的测试,软件测试更依赖整个团队的共同努力。
  • 敏捷测试的实践具有鲜明的敏捷开发的特征,与传统测试的区别,可以概况如下:
    1. 传统测试更强调测试的独立性,将“开发人员”和“测试人员”角色分得比较清楚,而敏捷测试可以有专职的测试人员,也可以是全民测试,即在敏捷测试中,可以没有“测试人员”角色,强调整个团队对测试负责。
    2. 传统测试更具有阶段性,从需求评审、设计评审、单元测试到集成测试、系统测试等,从测试计划,测试设计再到测试执行、测试报告等。但敏捷测试团队每一天都在一起工作,一起讨论需求,一起评审需求,更强调持续测试,持续的质量反馈,测试的持续性更为显著。
    3. 传统测试强调测试的计划性,认为没有良好的测试计划和不按计划执行,测试就难以控制和管理,而敏捷测试更强调测试的速度和适应性,侧重计划的不断调整以适应需求的变化。
    4. 传统测试强调测试是由“验证”和“确认”两种活动构成的,而敏捷测试没有这种区分,始终以用户需求为中心,每时每刻不离用户需求,将验证和确认统一起来。
    5. 传统测试强调任何发现的缺陷要记录下来,以便进行缺陷根本原因分析,达到缺陷预防的目的,并强调缺陷跟踪和处理的流程,区分测试人员和开发人员的各自不同的责任。而敏捷测试强调面对面沟通、协作,强调团队的责任,不太关注对缺陷的记录与跟踪。
    6. 传统测试更关注缺陷,围绕缺陷开展一系列的活动,而敏捷测试更关注产品本身,关注可以交付的客户价值,在快速交付的敏捷开发模式下,缺陷修复的成本很低。
    7. 传统测试鼓励自动化测试,但对于传统开发的周期比较长,即使没有自动化测试也是可以应付的,一般来说,回归测试能够获得几周时间,甚至一两个月的时间,自动化测试的成功与否对测试没有致命的影响。敏捷测试的持续性迫切要求测试的高度自动化,在1-3天内就要完成整个的验收测试(包括回归测试)。没有自动化,就没有敏捷,自动化测试是敏捷测试的基础。
  • 探索测试强调测试的学习、设计和执行同时展开,也就是没有测试用例
  • 软件测试5个学派
    1. 分析学派:认为软件是逻辑性的,将测试看作计算机科学和数学的一部分,结构化测试、代码覆盖率就是其中一些典型的例子。他们认为测试工作是技术性很强的工作,侧重使用类似UML工具进行分析和建模。
    2. 标准学派:从分析学派分离出来并得到IEEE的支持,把测试看作侧重劣质成本控制并具有可重复标准的、旨在衡量项目进度的一项工作,测试是对产品需求的确认,每个需求都需要得到验证。
    3. 质量学派:软件质量需要规范,测试就是过程的质量控制、揭示项目质量风险的活动,确定开发人员是否遵守规范,测试人员扮演产品质量的守门员角色。
    4. 上下文驱动学派:认为软件是人创造的,测试所发现的每一个缺陷都和相关利益者密切相关;认为测试是一种有技巧的心理活动;强调人的能动性和启发式测试思维。探索性测试就是其典型代表。
    5. 敏捷学派:认为软件是持续不断的对话,而测试就是验证开发工作是否完成,强调自动化测试。TDD是其典型代表。
  • 基于风险的测试是指评估测试的优先级,先进行高优先级的测试,如果时间或精力不够,低优先级的测试可以暂时先不做。基于风险的测试,也就是根据事情的轻重缓急来决定测试工作的重点和工作的顺序。
  • 过程能力描述了遵循一个软件测试过程可能达到的预期结果的范围。
  • TMM也将测试过程成熟度分为5个等级——初始级、定义级、集成、管理&度量、优化。

第五章 单元测试与集成测试

  • 单元测试是对单元的代码规范性、正确性、安全性、性能等进行验证。
  • 通过单元测试,需要验证下列这些内容:
    1. 数据或信息能否正确地流入和流出单元。
    2. 在单元工作过程中,其内部数据能否保持其完整性,包括内部数据的形式、内容及相互关系不发生错误,也包括全局变量在单元中的处理和影响
    3. 在数据处理的边界处能否正确工作。
    4. 单元的运行能否做到满足特定的逻辑覆盖。
    5. 单元中发生了错误,其中的出错处理措施是否有效。
    6. 指针是否被错误引用、资源是否及时被释放。
    7. 有没有安全隐患?是否使用了不恰当的字符串处理函数等。
  • 通过单元测试的一般标准
    1. 软件单元功能与设计需求一致。
    2. 软件单元接口与设计需求一致
    3. 能够正确处理输入和运行中的错误。
    4. 在单元测试中发现的错误已经得到修改并且通过了测试。
    5. 达到了相关的覆盖率的要求。
    6. 完成软件单元测试报告。
  • 单元测试的任务包括单元中所有独立执行路径、数据结构、接口、边界条件、容错性等测试。
  • 单元独立执行路径的测试,主要检查下列问题
    1. 误解或用错了算符优先级;
    2. 混合类型运算;
    3. 变量初始化错误、赋值错误;
    4. 错误计算或精度不够;
    5. 表达式符号错等。
  • 单元局部数据结构的测试,发现下面几类错误:
    1. 不合适或不相容的类型说明;
    2. 变量无初值;
    3. 变量初始化或缺省值有错;
    4. 不正确的变量名(拼错或不正确地截断);
    5. 出现上溢、下溢和地址异常。
  • 单元接口测试应该考虑下列主要因素:
    1. 输入的实际参数与形式参数的个数、类型等是否匹配、一致;
    2. 调用其他单元时所给实际参数与被调用单元的形式参数个数、属性和量纲是否匹配;
    3. 调用预定义函数时所用参数的个数、属性和次序是否正确;
    4. 是否存在与当前入口点无关的参数引用;
    5. 是否修改了只读型参数;
    6. 对全程变量的定义各单元是否一致;
    7. 是否把某些约束作为参数传递。
  • 单元容错性测试着重检查下列问题:
    1. 输出的出错信息难以理解;
    2. 记录的错误与实际遇到的错误不相符;
    3. 在程序自定义的出错处理代码运行之前,系统已介入;
    4. 异常处理不当;
    5. 错误陈述中未能提供足够的定位出错信息。
  • 代码审查包括互查、走查、会议评审等形式。
  • 驱动程序也称为驱动模块,用以模拟被测试模块的上级模块,能够调用被测试模块。在测试过程中,驱动模块接收测试数据,调用被测模块并把相关的数据传送给被测模块。
  • 桩程序,也称为桩模块,用以模拟被测模块工作过程中所调用的下层模块。
  • 对于类的单元测试可以看作是对类的成员函数进行测试。
  • 5.4代码评审案例分析(5个)
  • 单元测试工具JUnit、CppUnit、NUnit、HtmlUnit、JsUnit、PhpUnit、PerlUnit、XmlUnit
  • 代码静态检测工具CheckStyle 、FindBugs、PMD
  • 集成测试的模式:非渐增式测试模式和渐增式测试模式;两种模式的优缺点:
    1. 渐增式测试模式需要编写的软件较多,工作量较大,而非渐增式测试模式开销小;
    2. 渐增式测试模式发现模块间接口错误早,而非渐增式测试模式晚;
    3. 非渐增式测试模式发现错误,较难诊断,而使用渐增式测试模式,如果发生错误则往往和最近加进来的那个模块有关。
    4. 渐增式测试模式更彻底;
    5. 渐增式测试模式需要较多的机器时间。
    6. 使用非渐增式测试模式可以并行测试。

第六章系统测试

  • 系统测试一般由若干个不同测试类型组成,目的是充分运行系统,验证整个系统是否满足功能和非功能性的质量需求。
  • 非功能:压力测试、容量测试和性能测试
  • 选择回归测试策略应该兼顾效率和有效性两个方面,下面有几种方法:
    1. 再测试全部用例。
    2. 基于风险选择测试。
    3. 基于操作剖面选择测试。
    4. 再测试修改的部分
  • 性能测试就是为了发现系统性能方面或获取系统性能相关指标(如运行速度、响应时间、资源使用率等)而进行的测试。
  • 系统的性能指标包括两个方面的内容——系统资源(CPU、内存)的使用率和系统行为表现。资源使用率越低,一般来说系统会有更好的性能表现,系统资源使用率很高甚至耗光,系统的性能肯定不会好。资源利用率是分析系统性能指标进而改善性能的主要依据。
  • 系统行为的性能指标很多,常见的有以下几个:
    1. 请求响应时间;
    2. 事物响应时间;
    3. 数据吞吐量;
  • 性能测试,根据其不同的测试目的分为以下几类:
    1. 性能验证测试,验证系统是否达到事先已定义的系统性能指标、能否满足系统的性能需求。
    2. 性能基准测试,在系统标准配置下获得有关的性能指标数据,作为将来性能改进的基准线。
    3. 性能规划测试,在多种特定的环境下,获得不同配置的系统性能指标,从而决定在系统部署时采用什么样的软、硬件配置。
    4. 容量测试
  • 负载加载的方式:逐步加载、平均加载、随机加载、峰谷交替加载。
  • 性能测试过程:
    1. 确定性能测试需求,包括确定哪些性能指标要度量的,以及系统会承受哪些负载。
    2. 根据测试需求,选择测试工具和开发相应的测试脚本。
    3. 建立性能测试负载模型,就是确定并发虚拟用户的数量,每次请求的数据量、思考时间、加载方式和持续加载的时间。
    4. 执行性能测试。通过多次运行性能测试负载模型,获得系统的性能数据。
    5. 提交性能测试报告,包括性能测试方法、负载模型和实际执行的性能测试、性能测试结果及其分析。
  • 在测试过程中,要善于捕捉被监控的数据曲线发生突变的地方——拐点,这一点就是饱和点或性能瓶颈。
  • 压力测试,也称为强度测试、负载测试。压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷,长时间或超大负荷地运行测试软件,来测试被测系统的性能、可靠性、稳定性等。压力测试的目的就是在软件投入使用以前或软件负载达到极限以前,通过执行可重复的负责测试,了解系统可靠性、性能瓶颈等,以提高软件系统的可靠性、稳定性,减少系统的宕机时间和因此带来的损失。
  • 容量测试,预先分析出反映软件系统应用特征的某项指标的极限值,如某个web站点可以支持的多少个并发用户的访问量、网络在线会议系统的与会人员。
  • 安全性要求分析,包括确定可能的或潜在的各类安全威胁和找到处理这些威胁的策略。
  • 安全性测试就是全面检验软件在需求规格说明书中规定的防止危害状态措施的有效性和在每一个危险状态下的反应,对软件设计中用于提高安全性的结构、算法、容错、冗余、中断处理等方案进行针对性测试,并对安全性关键的软件单元和软件部件,单独进行加强的测试,以确认其满足安全性需求。
  • 理论上讲,只要有足够的时间和资源,没有不可进入的系统。因为系统安全设计的准则是,使非法侵入的代价超过被保护信息的代价,此时非法侵入者已无利可图。
  • 安全性一般分为两个层次,即应用程序级别的安全性和系统级别的安全性。应用程序级别的安全性:核实操作者只能访问其所属用户类型已被授权访问的那些功能或数据。系统级别的安全性:核实只有具备系统和应用程序访问权限的操作者才能访问系统和应用程序。
  • 他们的关系:
    1. 应用程序级别的安全性,包括对数据或业务功能的访问;系统级别大安全性,包括系统的登录或远程访问。
    2. 应用程序级别的安全性可确保:在预期的安全性情况下,操作者只能访问特定的功能或用例,或者只能访问有限的数据;
    3. 系统级别的安全性可确保只有具备系统访问权限的用户才能访问应用程序,而且只能通过相应的网关来访问。
  • 根据GB17859-1999,确定系统安全性的5个级别:
    1. 用户自主保护级
    2. 系统审计保护级
    3. 安全标记保护级
    4. 结构化保护级
    5. 访问验证保护级
  • Web的安全性测试中,通常需要考虑下列的情形:
    1. 数据加密
    2. 登录或身份验证
    3. 输入验证
    4. SQL注入
    5. 超时限制
    6. 目录
    7. 操作留痕
  • 容错性测试主要检查系统的容错能力,检查软件在异常条件下自身是否具有防护性的措施或者某种灾难性恢复的手段。
  • 对于自动恢复需验证重新初始化、检查点、数据恢复和重新启动等机制的正确性;对于人工干预的恢复系统,还需估算平均修复时间,确定其是否在可接受的范围内。
  • 可靠性是产品在规定的条件下和规定的时间内完成规定功能的能力,它的概率度量称为可靠度。
  • 软件可靠性是软件系统在规定的时间内及规定的环境条件下,完成规定功能的能力。
  • 软件可靠性测试,也称软件可靠性评估,指根据软件系统可靠性结构、寿命类型和各单元的可靠性试验信息,利用概率统计方法,评估出系统的可靠性特征量。
  • 软件可靠性模型分为两大类,即软件可靠性结构模型和软件可靠性预计模型。
  • 软件可靠性结构模型是依据系统结构逻辑关系,对系统的可靠性特征及其发展变化规律做出可靠性评价。此模型既可用于软件可行性综合评价又可用于软件可靠性分解。
  • 软件可靠性预计模型则是用来描述失效与软件缺陷的关系,借助这类模型,可以对软件的可靠性特征做出定量的预计或评估。
  • 预计模型有以下几类
    1. 面向时间的预计模型,以时间为基准,描述软件可靠性特征随时间变化的规律。
    2. 面向输入数据的预计模型,描述软件可靠性与输入数据的联系,利用程序运行中的失效次数与成功次数的比作为软件可靠性的度量。
    3. 面向错误数的预计模型。,描述程序中现存错误数的多少预示程序的可靠性。
  • ISO9000 国际质量标准(ISO/IEC9126-1991)规定,软件产品的可靠性含义是:在规定的一段时间和条件下,软件能维持其性能水平的能力有关的一组属性,可用成熟性、容错性、易恢复性三个基本子特性来度量。
  • 成熟性度量可以通过错误发现率来表现。
  • GJB438A-1997中,软件测试报告应具备下列内容:
    1. 产品标识
    2. 使用的配置
    3. 使用的文档
    4. 产品说明、用户文档、程序和数据的测试结果。
    5. 与需求不相符项的列表
    6. 测试的最终日期

第七章 验收测试

  • 验收测试是在软件产品完成了功能测试和系统测试之后,产品发布之前所进行的软件测试活动。
  • 验收测试是检验产品和产品规格说明书的一致性。
  • 好的用户界面包含7个要素:
    1. 符号标准和规范
    2. 直观性
    3. 一致性
    4. 灵活性
    5. 舒适性
    6. 正确性
    7. 实用性
  • 安装测试时,一般要注意一下几个方面
    1. 一般严格按照安装文档中的说明,一步一步地进行操作,最好从文档中复制出各种操作命令及其参数,确保输入到计算机的命令和文档中的内容一致。检查系统安装是否能够安装所有需要的文件、数据并完成必要的系统设置。
    2. 软件的安装说明书有无对安装环境做限制和要求。至少在标准配置和最低配置两种环境下安装。
    3. 安装过程是否简单,容易掌握
    4. 安装过程是否有明显的、合理的提示信息。
    5. 卸载测试也是安装测试的一部分。
    6. 安装过程中是否会出现不可预见的或不可修复的错误,进一步验证安装过程中对硬件的识别能力、是否会破坏其他文件或配置。
    7. 安装程序是否占用太多系统资源、是否有冲突、是否会影响原系统的安全性。
    8. 软件安装的完整性和灵活性。
    9. 软件使用的许可号码或注册号码的验证,用户许可协议的条款要保证其合理、合法。

第八章 软件本地化测试

  • 软件本地化是将一个软件产品按特定国家或语言市场的需要进行全面定制的过程,包括翻译、重新设计、功能调整以及功能测试、是否符合各个地方的习俗、文化背景、语言和方言的验证等。
  • 为了减少本地化的工作,软件产品国际化应该具有下面一系列特性:
    1. 支持Unicode字符集;
    2. 分离程序代码和显示内容(文本、图片、对话框、信息框和按钮等)如将这些内容由资源文件统一处理。
    3. 消除硬代码(hard code,指程序代码中所包含一些特定的数据,它们本应该作为变量处理,而对应的具体数据应该存储在数据库或初始化文件中);
    4. 使用Header Files去定义经常被调用的代码段;
    5. 改善翻译文本尺寸,具体调整的灵活性,如在资源文件中可以直接具有调整用户界面的灵活性来适应翻译文本尺寸。
    6. 支持各个国家的键盘设置,并有对应的热键处理;
    7. 支持文字不同方向的显示;
    8. 支持各个国家的度量衡、时区、货币单位格式等自定义功能;
    9. 用户界面(包括颜色、字体等)自定义特性
  • 软件本地化基本步骤:
    1. 建立一个配置管理体系,跟踪目标语言各个版本的源代码;
    2. 创造和维护术语表;
    3. 从源语言代码中分离资源文件或提取需要本地化的文本;
    4. 把分离或提取的文本、图片等翻译成目标语言;
    5. 把翻译好的文本、图片重新插入目标语言的源代码版本中;
    6. 如果需要,编译目标语言的源代码;
    7. 测试翻译后的软件,调整UI以适应翻译后的文本;
    8. 测试本地化后的软件,确保格式和内容都正确。
  • 本地化测试着重与以下几个方面
    1. 主要的功能性测试,函数之间传递的参数、数据库的默认值经过本地化处理后,可能会对系统的功能运行产生较大的影响,从而引起功能缺陷。
    2. 在本地化环境中的安装和升级测试,由于目标语言的操作系统和软件本身都不一样了,安装或升级过程也常常受到影响;
    3. 根据产品的目标区域而进行的应用程序和硬件兼容性测试,其应用程序的接口、标准可能不同,硬件型号及其配置更有可能存在差异;
    4. 受本地化影响的用户界面,包括布局、格式、文字和图片等内容显示问题;
    5. 特殊的语言环境(意境)、文化背景和地理位置等可能给软件带来的问题;
    6. 文字翻译的正确性、准确性以及是否遗漏等。
  • 针对用户界面和语言文化方面的测试,其具体内容包括以下几个方面。
    1. 应用程序源文件的有效性;
    2. 验证语言的准确性和源代码的属性;
    3. 排版错误;
    4. 检查印刷文档和联机帮助、界面信息的一致性以及命令键的顺序等;
    5. 用户界面是否符合当地审美标准(或情趣);
    6. 文化适用性的评估;
    7. 政治敏感内容的检查。

第九章 测试自动化及其框架

  • 自动化测试是相对手工测试而存在的一个概念,有手工逐个地运行测试用例的操作过程被测试工具或系统自动执行的过程代替,包括输入数据自动生成、结果的验证、自动发送测试报告等。主要是通过所开发的软件测试工具、脚本等来实现,具有良好的可操作性、可重复性和高效率等特点。测试自动化是软件测试中提高测试效率、覆盖率和可靠性等重要手段。
  • 手工测试的局限性
    1. 通过手工测试无法做到覆盖所有代码路径,也难以测定测试的覆盖率;
    2. 通过手工测试很难捕捉到与时序、死锁、资源冲突、多线程等有关的错误;
    3. 在系统负载、性能测试时,需要模拟大量数据或大量并发用户等大负载的应用场合时,没有测试工具的帮助是无法想象的。
    4. 在系统可靠性测试中,需要模拟系统运行几年、十几年,以验证系统能否稳定运行,也是手工测试无法模拟的。
    5. 在回归测试中,多数情况下时间很紧,希望一天能完成成千上万个测试用例的执行,手工测试,即使然测试人员通宵达旦地干,也干不完;
    6. 测试可以发现错误,并不能表明程序的正确性。
  • 自动化测试的优势:
    1. 自动运行的速度快、执行效率高,是手工无法相比的。
    2. 永不疲劳。
    3. 测试结果准确。
    4. 可靠。
    5. 可复用性。
    6. 特别的能力
  • 最早进行代码分析的工具是编译器。
  • 脚本是一组测试工具执行的指令集合,也是计算机程序的一种形式。脚本可以通过录制测试的操作产生,然后再做修改,这样可以减少脚本开发的工作量。
  • 结构化脚本具有很好的可重用性、灵活性,所以结构化脚本易于维护。
  • 数据驱动脚本,将测试脚本和数据分离开来,测试输入数据存储在独立的(数据)文件中,而不是存储在脚本中。
  • 测试工具的分类
    1. 根据测试方法不同,分为白盒测试工具和黑盒测试工具,或者分为静态测试工具和动态测试工具等。
    2. 根据测试的对象和目的不同,分为单元测试工具、功能测试工具、负载测试工具或性能测试工具、测试管理工具等。
  • 测试工具的选择步骤
    1. 成立小组负责测试工具的选择和决策,制定时间表;
    2. 确定自己的需求,研究可能存在的不同解决方案,并进行利弊分析;
    3. 了解市场上满足自己需求的产品,包括基本功能、限制、价格和服务等;
    4. 根据市场上产品的功能、限制和价格,结合自己的开发能力、预算、项目周期等决定是自己开发,还是购买;
    5. 对市场上的产品进行对比分析,确定两三种产品作为候选产品;
    6. 请候选产品的厂商来介绍、演示,并解决几个实例;
    7. 初步确定;
    8. 商务谈判;
    9. 最后决定。
  • 自动化测试时没有达到预期效果,没有让测试工具发挥应有的作用。主要原因有:
    1. 不正确的观念或不现实的期望;
    2. 缺乏具有良好素质、经验的测试人才;
    3. 测试工具本身的问题影响测试的质量;
    4. 没有进行有效的、充分的培训;
    5. 没有考虑到公司的实际情况,盲目引入测试工具;
    6. 没有形成一个良好的使用测试工具的环境;
    7. 其他技术问题和组织问题。
  • 测试自动化框架:
    1. harness/IDE
    2. 自动化测试脚本的管理
    3. 代理负责Harness与工具的通信,控制测试工具的运行。
    4. 测试工具
    5. 任务安排
    6. 报告呈现,任何一个人都能以Web方式及时查到测试结果。

大题

对于YMD三个参数,NEXT函数应该是得出他的下一天

假设年在2000到2022有效

输入 有效等价类 无效等价类
Y 1. [2000-2022]之间的整数 2. (-∞,2000)的整数
3. (2022,+∞)的整数
4. 小数字母等无效输入
D 5. [1-28]的整数
6. 29
7. 30
8. 31
9. (-∞,1)的整数
10. (31,+∞)的整数
11. 29
12. 30
13. 31
14. 小数字母等无效输入
M 15. [1-12]的整数 16. (-∞,1)的整数
17. (12,+∞)的整数
18. 小数字母等无效输入

无效

Y D M 异常
1. 1999 1 1 Y2. (-∞,2000)的整数
2. 2023 1 1 Y3. (2022,+∞)的整数
3. Abcd 1 1 Y4. 小数字母等无效输入
4. 2000 0 1 D9. (-∞,1)的整数
5. 2000 32 1 D10. (31,+∞)的整数
6. 2021(不是闰年) 29 2 D11. 29
7. 2021(不是闰年) 30 2 D12. 30
8. 2000 31 4 D13. 31
9. 2000 0.1a 1 D14. 小数字母等无效输入
10. 2000 1 0 M16. (-∞,1)的整数
11. 2000 1 13 M17. (12,+∞)的整数
12. 2000 1 A M18. 小数字母等无效输入

有效

Y D M 说明
1. 2000 1 1 Y1. [2000-2022]之间的整数
D5. [1-28]的整数
M15. [1-12]的整数
2. 2000 29 1 Y1. [2000-2022]之间的整数
D6. 29
M15. [1-12]的整数
3. 2000 30 1 Y1. [2000-2022]之间的整数
D7. 30
M15. [1-12]的整数
4. 2000 31 1 Y1. [2000-2022]之间的整数
D8. 31
M15. [1-12]的整数

根据如图所示程序流程图,分别用最少的测试用例完成语句覆盖、判定覆盖的测试设计

image-20220330163023449

if(x > 0 && y > 10){
y=y/x;
}
if(x < -10 || y < 0){
y=-(y + x)
}

x=1 y=11 的情况

满足第一个分支 y=11

不满足第二个分支

x=-11 y=1 的情况

不满足第一个分支

满足第二个分支 y=10

上边这两条测试用例就可以做到语句覆盖,我没有找到一条覆盖所有的用例

并且上边这两条测试用例也可以做到判定覆盖

三(做的有问题)

根据如图所示程序流程图,分别用最少的测试用例完成基本路径覆盖、条件/判定覆盖的测试设计

image-20220330163059592

存在的组合示例

组合编号 1(x > 0)
3(x < -10)
2(y > 10)
4(y < 0)
判定条件取值 判定/条件组合
1 T1 T2 M=T x > 0,y > 10,M取真
2 T1 F2 M=F x > 0,y <= 10,M取假
3 F1 T2 M=F x <= 0,y > 10,M取假
4 F1 F2 M=F x <= 0,y <= 10,M取假
5 T3 T4 N=T x < -10,y < 0,N取真
6 T3 F4 N=T x < -10,y >= 0,N取真
7 F3 T4 N=T x >= -10,y < 0,N取真
8 F3 F4 N=F x >= -10,y >= 0,N取假

条件/判定覆盖

让所有的判定结果至少出现一次,即覆盖组合存在1-8所有

if(x > 0 && y > 10){//M
y=y/x;//1
}//2
if(x < -10 || y < 0){//N
y=-(y + x)//3
}//4

测试用例

测试用例 覆盖条件 覆盖路径 覆盖组合
输入:x=1,y=11
输出:x=1,y=11
T1,T2,F3,F4 1-4 1,8
输入:x=1,y=-1
输出:x=1,y=0
T1,F2,F3,T4 2-3 2,7
输入:x=-11,y=11
输出:x=-11,y=0
F1,T2,T3,F4 2-3 3,6
输入:x=-11,y=-11
输出:x=-11,y=22
F1,F2,T3,T4 2-3 4,5

基本路径覆盖

覆盖所有可能的路径,即1,3|1,4|2,3|2,4

if(x > 0 && y > 10){//M
y=y/x;//1
}//2
if(x < -10 || y < 0){//N
y=-(y + x)//3
}//4

基本路径

  1. 画流程图

329.drawio

  1. 计算程序环路复杂度

    1. V(G)=区域数目=2
    2. V(G)=边界数目-节点数目+2=4-4+2=2
    3. V(G)=判断节点数目+1=1+1=2(出度>=2)
  2. 确定基本路径

    • 1-4
    • 2-3

测试用例

测试用例 覆盖条件 覆盖路径 覆盖组合
输入:x=1,y=11
输出:x=1,y=11
T1,T2,F3,F4 1-4 1,8
输入:x=1,y=-1
输出:x=1,y=0
T1,F2,F3,T4 2-3 2,7

下边是用于计算输出和路径统计的代码

let x = -11;
let y = -11;
//////////////////////////
if (x > 0) {
console.log("T")
}
else {
console.log("F")
}
if (y > 10) {
console.log("T")
}
else {
console.log("F")
}
//////////////////////////
if (x > 0 && y > 10) {
y = y / x;
console.log("1");
}else{
console.log("2");
}
//////////////////////////
if (x < -10) {
console.log("T")
}
else {
console.log("F")
}
if (y < 0) {
console.log("T")
}
else {
console.log("F")
}
//////////////////////////
if (x < -10 || y < 0) {
y = -(y + x);
console.log("3");
}else{
console.log("4");
}
//////////////////////////
console.log("x", x);
console.log("y", y);