🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀软件开发必练内功_十二月的猫的博客-CSDN博客💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光
目录
1. 前言
在进入本篇文章前,大家可以按需求看看另几篇文章:
【软件工程】第二章·软件过程(过程与生命周期建模)-CSDN博客
【软件工程】第三章·计划和管理项目(详解活动图计算关键路径、最早开始时间、最晚开始时间、冗余时间)-CSDN博客
【软件工程】第六章·考虑对象(UML、UML在软件开发中的应用、面向对象方法的软件开发)-CSDN博客
这几篇文章将让你对软件工程有一个整体的脉络,并在细节上有一定的把控。
本文参考书籍:软件工程 第4版( [美] 莎丽·劳伦斯·弗里格(Shari Lawrence Pfleeger))
2. 前景知识回顾
第一章·软件工程概述:
1、软件工程是什么——定义、方法、作用。
2、软件工程的前世今生——出现的问题(error、fault、failure)、应对方法(问题分析方法+系统化方法+工程化方法)。
3、软件工程的未来——Wasserman 规范(抽象、分析设计方法和符号描述系统、软件过程、软件体系结构、重用和复用、用户界面原始模型、测试代码、工具和集成环境)
第二章·软件过程与生命周期:
1、过程与生命周期是什么
- 过程是一系列有序的任务,涉及活动、资源和约束(过程不是步骤而是步骤的集合)。
- 生命周期是软件从概念、实现、交付到使用、维护的整个过程。软件开发全过程称为软件生命周期。
2、过程模型
- 种类:瀑布模型、原型化瀑布模型、V模型、原型化模型、阶段化开发模型、螺旋模型、敏捷方法模型
- 联系:
- 瀑布模型是基础。
- 原型化瀑布模型结合原型化模型与瀑布模型(设计阶段产生原型化模型,在测试阶段考虑是否返回)。
- V模型(将设计与测试之间都建立起通道)。
- 原型化模型(不是具体模型,是一种思想,每一个步骤都可以产生原型去分析)。
- 阶段化开发模型(开发版本和使用版本分离,分离导致需要选择迭代开发/增量开发/迭代进化开发/统一过程开发)。
- 螺旋模型(是迭代思想和原型化思想的结合)。
- 敏捷方法模型(撇弃原型化和迭代化带来的冗余,将目标转化为:快【尽早交付】、准【持续有价值的软件交付活动】、狠【直到客服满意】)(四大原则:个体和交互胜过过程和工具、可运行软件胜过面面俱到的文档、客户合作胜过合作谈判、响应变化胜过遵循计划)
- 核心思想:迭代思想、增量思想、原型化思想
第三章·计划和管理项目:
1、计划项目
- 时间计划:项目进度、项目活动、里程碑、活动图、最早开始时间、最迟开始时间、冗余时间、关键路径。
- 工作量计划:估(专家估算:Delphi技术、乐观悲观法、Wol技术)、算(算式公式:(a+bSc)m(X)、COCOMO模型:aKLOC^b)
2、管理项目
- 人员管理:人员技术、工作方式、项目组织安排(结构性与创造性、一个领导模式、忘我方法模式)
- 风险管理:什么是风险、风险管理活动(风险评价:风险识别、风险优先级、风险分析)(风险控制:风险降低、风险化解、风险管理计划)、风险降低(风险避免、假设风险、转移风险)、风险化解(6种风险的6种应对方式:产品过大、功能复杂、系统不支持、测试时间、产品控制、协同工作)
第四章·需求分析:
- 了解需求:需求是什么(需求是用户对软件系统期望行为的综合描述)、需求的类型(功能性需求、非功能性需求)、需求的特征(一致性、正确性、无二义性、完备性、可行性等)、需求的表示(UML图)
- 引出需求:风险承担者、引出需求的方式(会谈、特别关注、观察、查看文档)
- 需求前期处理:优先级划分、需求规范化(正式名字、唯一定义、量化描述)
- 需求下的约束:设计约束(之前的设计决策对现在决策的约束)、过程约束(现在技术和资源对决策的限制)
- 需求分析全过程:原始需求获取、问题分析、规格说明草稿、需求核准、软件规格说明书(SRS)
第五章·系统体系结构:
- 系统体系结构设计相关概念:体系结构、设计、例程设计、创新设计、克隆、参考模型、体系结构风格、设计模式、设计原则、设计公约、模块化、概念/技术设计。
- 系统体系结构设计全过程:建模、分析、文档化、复审、形成最终文档(SAD)。
- 体系结构质量标准:可修改性、可维护性、性能、安全性、可靠性、健壮性等。
- 建模核心——分解:分解是什么、分解的六大方法。
- 分解目的——模块化:模块化是什么、模块化的目的——模块独立性(内聚与耦合)。
- 体系结构的评估改进:故障树与割集树、错误语法与处理、复审(验证与确认)
- 常见的体系结构:管道和过滤器、隐含调用、面向对象、CS、发布订阅、分层等。
第六章·考虑对象:
- UML统一建模语言:几大类型的图(在不同层面反应软件系统的特点)
- UML建模语言在软件开发中的应用:需求分析(用例图、概念类图、数据流图)、设计(对象图、类图、活动图、状态图、顺序图和协作图)、编码与测试(包图、部署图、构件图)
- 面向对象的软件开发:什么是面向对象(含义、七大特征、优势、三个观点)、面向对象开发过程概述(需求分析:确定类、确定类的动态行为)(设计:系统设计、程序设计)(编码与测试)、面向对象开发过程详细(加入UML图更加详细说明每一个部分需要干的事情)
第七章·编写程序:
- 编程标准:编程包括(代码编写+文档书写)、编程标准对自身的作用(早期、中期与后期)、编程标准对他人的作用(重用、测试与维护)、最大的编程标准(设计与编程实现相匹配)
- 编程指导原则:三个角度指导编程(数据结构、算法、控制结构)、通用编程策略(重用、设计包含伪代码、改动时重新开始不打补丁、局部化输入输出
- 文档化:内部文档(头注释块、变量名和语句注释、过程注释)、外部文档
- 编程过程:编程全过程(理解问题、制定计划、执行计划和回顾)、极限编程(交流、勇气、简单性以及反馈)、结对编程
3. 章节概述和章节框架
明确一个点:Wasserman 规范(抽象、分析设计方法和符号描述系统、软件过程、软件体系结构、重用和复用、用户界面原型、测试、工具和集成环境)贯穿软件开发全过程。
章节联系:本章节就是Wasserman规范中的一个。通过前面的学习,我们已经接触了软件过程(软件过程本身)、计划和管理软件项目(抽象)、需求分析(抽象)、软件体系结构(软件体系结构本身)、考虑对象(分析方法和符号描述系统)、编写程序(重用和复用、用户界面原型)【括号内为章节和Wasserman规范的对应】。接下来,我们学习测试,这也是Wasserman规范中重要的一部分。
对于任何一个系统,测试的过程都是必不可少的。测试并不想我们想象的一样单纯,它也有自己的一套体系流程。本章介绍的就是有关测试的前半部分——单元测试和集成测试。将重新深入地认识故障和失效,了解测试的目的、流程和方法。如何从单元测试到将单元集成一个系统也是本章学习的内容。
4. 单元/集成测试
4.1 故障和失效
为什么我们需要测试,因为程序不可避免的存在故障和失效的情况。为了减少程序在交付后故障和失效情况的出现(那时修改代价很大),我们需要在程序开发完成后,程序交付前对程序进行测试,看看程序是否符合我们的期待。
测试的目的是发现错误而非证明正确性(假设软件系统存在错误)。
4.1.1 故障(falut)
故障(falut)的定义:由错误(error)引起的系统内在问题。【着眼于软件运行】
故障出现的原因:
(1)软件本身,系统处理大量的状态,复杂的公式,活动,算法等;
(2)客户不清晰的需求;
(3)其他原因,如项目的规模,众多的参与者导致的复杂性。
4.1.2 失效(failure)
失效的定义:软件的动作与需求描述的不相符。【着眼于用户使用】
造成失效的原因:
(1)错误的规格说明,或者遗漏了一些需求;
(2)对于指定的硬件和软件,说明中存在一些无法完成的实现;
(3)错误的系统设计;
(4)错误的程序设计,错误的实现。
故障的识别(fault identification):是确定由哪一个或者哪些故障引起失效的过程。
故障改正(fault correction)或故障去除(fault removal):修改系统使得故障得以去除的过程。
4.1.3 故障的分类
为什么对故障进行分类:
1、错误是程序员犯的,难以预知(他如果知道,他也不会犯错啦😂)
2、故障是错误的外在表现,很直观可见。
3、失效是用户使用中发现的,这个时候才知道就不好了。
分类的原因:知道正在处理的是什么类别的故障对于我们具体的测试,以及之后的故障改正都是有很大帮助的。
具体分类:
(1)算法故障(algorithmic fault):由于处理步骤中的某些错误,使得对于给定的输入,构件的算法或逻辑没有产生适当的输出。
(2)计算故障(computation fault)或精读故障(precision fault):一个公式的实现是错误的,或者计算结果没有达到要求的精度。
(3)文档故障(documentation fault):文档与程序实际做的事情不一致。(倾向于相信文档)
(4)过载故障(overload fault):对队列长度、缓冲区大小、表的维度等的使用超出了规定的能力。(数据上不可接受)
(5)能力故障(capacity fault):系统活动到达指定的极限时,系统性能会变得不可接受。(用户数量、活动数量不可接受)
(6)时序故障(timing fault):几个同时执行或仔细定义顺序执行的进程之间细条不适当。
(7)性能故障(performance fault):系统不能以需求规定的速度执行。
(8)恢复故障(recovery fault):当系统失效时,不能表现得像设计人员希望的或客户要求的那样。
(9)硬件和系统软件故障(hardware and system software fault):当提供的硬件或者系统软件实际上并没有按照文档中的操作条件或步骤运作时。
(10)标准和过程故障(standards and procesure fault):代码没有遵循组织机构的标准和过程。
4.1.4 正交缺陷分类
定义:被分类的任何一项故障都只属于一个类别,则分类方案是正交的。如果一个故障属于不止一个类,则失去了度量的意义。
上面提出的故障类型(fault type)一定要是彼此正交的。
4.2 测试之前应该明确的几个问题
4.2.1 测试分类
(1)单元测试(unittesting):将每个程序构件与系统中的其他构件隔离,对其本身进行测试。
(2)集成测试(integration testing):验证系统构件是否能够按照系统和程序设计规格说明中描述的那样共同工作的过程。
(3)功能测试(function test):对系统进行评估,以确定集成的系统是否确实执行了需求规格说明中描述的功能,其结果是一个可运转的系统。
(4)性能测试(performance test):测试系统的软硬件性能是否符合需求规格说明文档。其结果是一个确认的系统。
(5)验收测试(acceptance test):确定系统是按照用户的期望运转的。
(6)安装测试(installation test):确保系统在实际环境中按照应有的方式运转。
系统测试(system test):功能测试、性能测试、验收测试和安装测试统称为系统测试。
4.2.2 测试的态度
- 正确的态度应该是将测试看成是一个发现的过程。
- 不仅仅将程序视作问题的解决方案,同样考虑问题本身是否存在问题。
- 当出现故障或者失效的时候,关注的是修改故障,而不是谴责某个开发人员。
4.2.3 谁执行测试——独立的测试团队
(1)开发人员可能担心发现系统故障影响自己的业绩,独立的测试团队避免了故障的个人责任与尽可能多的发现故障的需要之间的冲突;
(2)独立团队因为和代码不是太过紧密,所以能更加的客观,有更多的机会发现细微的故障;
(3)独立的测试团队可以参与软件开发的整个过程,测试可以和编码并行的进行。
4.2.4 测试的方法
1.黑盒:
将测试的对象看作是一个不了解其内容的闭盒(不了解内部结构),我们的测试就是向闭盒提供输入的数据,并记录产生的输出。测试的目标是确保针对每一种输入,观察到的输出与预期的输出相匹配。黑盒测试参考的文档是系统设计和程序设计阶段的文档。
优点:黑盒测试免于受强加给测试对象内部结构和逻辑的约束。更偏向于功能性的测试。
缺点:黑盒法以 SRS 为依据,有一定的盲目性和不确定性,不可能揭示所有的错误。没办法总是使用这种方式进行完备的测试。不容易找到具有代表性的测试用例证明所有情况下功能都正确。
黑盒测试的核心思想是 忽视内部实现,集中测试系统的功能性,确保系统按预期的方式工作,主要聚焦于 外部表现 和 用户需求。
2.白盒:
将测试对象看作一个白盒,然后根据测试对象的结构用不同的方式进行测试。
优点:可以测试一个模块的细节。
缺点:该法以模块内部逻辑为依据,当内部逻辑过于复杂时,则不能给出好的或合适的测试用例。有时候,对于大量递归、循环和分支的构件,想要测试完所有的分支也是不现实的。
3. 实际测试中:
没有必要把黑盒测试和白盒测试严格的区分开来。具体测试方法的选择受到很多因素的响。
4.3 单元测试
4.3.1 检查代码(通过代码复审)
代码复审(code review):由一个客观的专家组进行(代码复审),审查代码及其文档,查找误解、不一致性、性能问题和其他缺陷。
代码复审(code review)包括:代码走查(code walkthrough)和代码检查(code inspection)。代码走查非正式,代码审查相对正式,会事先准备关注问题清单,依据它比对代码和文档的一致性。
代码复审带来的好处:一个故障在开发过程中发现的越早,它就越容易纠正,所造成的损失也就越小。复审在检测故障方面表现得格外成功。
4.3.2 测试程序构件
测试用例(test case):用于测试程序的输入数据的一个特定选择。
测试的完全性:以一种使人信服的方式来证明测试数据展现了所有可能的行为。
(1)制定测试目标
(2)设计测试计划
(3)编写测试用例
(4)测试测试用例
(5)执行测试
(6)评估测试结果
1、测试计划:描述我们将以何种方式向用户证明软件运转正确。制定测试计划的时候要充分的了解需求、功能规格说明、系统设计和代码的模块层次结构。测试计划是随着系统本身的开发而制定的。
2、计划内容:针对测试的每一个阶段,测试计划详细描述执行每一步所使用的方法。每一种测试方法或技术还要附有一份详细的测试用例列表。测试计划的内容就是描述我们如何测试以及为什么执行测试。
4.3.2.1 黑盒测试方法
(1)等价分类法:将输入域划分为若干等价类。每一个测试用例都代表了一类与它等价的其他例子。如果测试用例没有发现错误,那么对应的等价例子也不会发生错误。有效等价类的测试用例尽量公用,以此来减少测试次数,无效等价类必须每类一个用例,以防止漏掉可能发现的错误。
(2)边界值分析法:在等价分类法中,代表一个类的测试数据可以在这个类的允许范围内任意选择。但如果把测试值选在等价类的边界上,往住有更好的效果,这就是边界值分析法的主要思想。
(3)错误猜测法:猜测程序中哪些地方容易出错,并据此设计测试用例。更多的依赖于测试人员的直觉和经验。
(4)因果图法:适用于被测试程序有很多输入条件,程序的输出又依赖输入条件的各种组合的情况。
4.3.2.1 白盒测试方法
(1)语句(覆盖)测试:在某次测试中,构件中的每条语句至少执行一次。
(2)分支测试:对代码中的每个判断点,每个分支在某次测试中至少选择一次。(每个分支都有一次就可以,不两两都组合过)
(3)路径测试:通过代码的每一条不同路径在某个测试中至少执行一次。(不仅每个分支都要走过一次,而且两两都要组合过)
对于这个图:
语句覆盖:选择 X 大于 K 使其产生正的 RESULT,就可以顺序执行 1-2-3-4-5-6-7 语句。
分支覆盖:图中有两个判断点,因此使用两个测试用例分别执行 1-2-3-4-5-6-7 和1-2-4-5-6-1 即可。
路径覆盖:图中可能路径包括:1-2-3-4-5-6-7、1-2-3-4-5-6-1、1-2-4-5-6-7、1-2-4-5-6-1 四条路径。
4.4 集成测试——得到一个正常运作的系统。
4.4.1 自底向上的集成
1.含义:使用这种测试方法的时候,每一个处于系统层次中最底层的构件先被单独测试,接着测试的是那些调用了前面已测试构件的构件。反复采用这种方法,知道所有的构件测试完毕。
2.构件驱动程序:代替上级模块传递测试用例的程序。
3.优点:测试用例比较容易生成;符合面向对象的开发思路。
4.缺点:顶层构件通常是最重要的,但是却是最后测试的。主要故障的测试将会推迟到测试的后期。(越到后期的故障越难处理)。
4.4.2 自顶向下的集成
1.含义:顶层构件通常是一个控制构件,是独立进行测试的。然后将被测构件调用的所有构件组合起来,作为一个更大的单元进行测试。重复这样的操作直到所有的构件都被测试。
2.桩(stub):代替下级模块的仿真程序
3.优点:一些功能性的设计故障或主要问题可以在测试的早期进行处理。
4.缺点:桩不容易编写,桩的正确性可能影响测试的有效性;另一个缺点是可能需要大量的桩。
这个模式下,桩需要能够完美代替下级模块的输出,这要求我们需要知道系统中每一个模块的正确输出,从而完成对上级模块的测试。这就导致测试用例的编写很有难度。
4.4.3 一次性集成
1.先测试每一个构件,然后将所有的构件一次性的集成。只适用于小型系统
2.缺点:
1、有些构件同时需要桩和驱动程序;
2、一次性集成,很难发现失效原因;
3、很难将接口故障和其他故障区分开。
4.4.4 三明治集成
含义:将系统分成三层,目标层处于中间、目标层上有一层,目标层下有一层。在顶层采用自顶向下的方式集成,在较低层采用自底向上的方式集成。测试集中于目标层。
4.5 测试面向对象的系统
在下面这篇文章中,我们第一次接触了面向对象开发方法。
【软件工程】第六章·考虑对象(UML、UML在软件开发中的应用、面向对象方法的软件开发)-CSDN博客
软件开发有很多方法,面向开发方法是其中最重要的方法,原因如下:
- 语言一致性
- 全开发过程一致性
因为这两个特性,在软件开发的所有步骤中都可以使用面向对象方法,并且自成一个开发体系。这个开发体系在软件开发质量标准中都非常高(耦合性低、内聚性高、性能好等) 。
上面那篇文章仅仅对需求分析、设计中面向对象方法的使用进行描述;而编码中的面向对象方法体现在java、c++等面向对象语言的使用,使用这些面向对象语言(类、对象等)我们能够很好使用面向对象特性。接下来,我们就来讲讲测试中的面向对象方法。
面向对象的测试有独特的特点,需要测试的时候需要一些额外的步骤。例如考察对类和对象进行考察,避免出现对象和类的过度和不足:遗漏对象、不必要的对象等。除此之外传统测试方法适用于功能,单很多方法没有考虑测试类所需的对象的状态。
面向对象开发方法中,各个步骤都是比传统软件开发要增加一些新的内容。
传统测试和面向对象测试的区别:
(1)测试用例的不可重用性:对过程语言而言,当系统改变时,我们可以针对改变测试是否正确,并使用原有的测试用例来验证剩余的功能是否同原来一致。但是面向对象的测试中,我们可能需要编写不同的测试用例。
(2)面向对象趋向于小粒度,并且平常存在于构件内的复杂性常常转移到构件之间的接口上。这意味着,其单元测试较为容易,但是集成测试涉及面变得更加广泛。
(3)传统测试和面向对象的测试主要集中在:需求分析和验证、测试用例生成、源码分析和覆盖分析。
5. 总结
本文到这里就结束啦~~
目前【软件工程】系列已经完成:
【软件工程】第二章·软件过程(过程与生命周期建模)-CSDN博客
【软件工程】第三章·计划和管理项目(详解活动图计算关键路径、最早开始时间、最晚开始时间、冗余时间)_体系运行各过程时间一览表-CSDN博客
【软件工程】第六章·考虑对象(UML、UML在软件开发中的应用、面向对象方法的软件开发)-CSDN博客
持续更新中🎢🎢🎢
如果觉得对你有帮助,友友们可以点个赞,收个藏呀~