第 133~156 题:软件工程
📚 本文是 信息基础大赛(10.29 备赛)的第 8 篇,题目以截图为主、文字为点拨。
基础概念
关注如何规划、设计、构建和维护高质量的软件应用程序。它涵盖了从需求分析到代码编写、测试、项目管理和质量保证的全过程,旨在提供可靠、高效和可维护的软件解决方案
软件危机(典型表现):
- 成本和进度:超预算、交付延期
- 质量:交付后缺陷多、不稳定,维护成本高
- 需求变更:客户需求频繁变更,增加复杂性和不确定性
- 复杂性增加:系统越来越复杂,设计/测试/维护挑战大
- 技术问题:新技术不成熟、难用
- 管理问题:缺乏适当的计划、监控和控制 → 混乱与失败
软件工程概论
软件工程三要素:方法、工具和过程。
- 方法(Methods):系统化的原则、规则和实践,指导需求分析、设计、编码、测试、项目管理。如敏捷方法、瀑布模型、结构化分析与设计、面向对象分析与设计
- 工具(Tools):支持/自动化开发过程的软件——代码编辑器、IDE、版本控制(Git)、项目管理(Jira)、测试自动化(Selenium)等,提高生产力与协作效率
- 过程(Process):相互关联的活动、任务和角色,规定项目执行步骤与协作方式。如瀑布、敏捷、Scrum、Kanban
三者协同:方法给指导原则,工具给支持自动化,过程规定如何协调管理。
软件开发生命周期
软件过程模型:
软件过程模型是软件开发的一种组织框架或方法论,它定义了软件项目的各个阶段、活动、任务和交付物,以及这些元素之间的关系。软件过程模型有助于规范和管理软件开发项目,确保项目按照一定的步骤和规则进行。
瀑布模型:
瀑布模型是一种线性和顺序的软件开发方法,将整个开发过程划分为一系列阶段,每个阶段的输出作为下一个阶段的输入。
阶段:典型的瀑布模型包括需求定义、系统设计、编码、测试、集成和维护阶段,各阶段按照顺序依次进行。
特点:瀑布模型强调在进入下一个阶段之前必须完成前一个阶段,且通常不支持大规模的变更或修改。这种方法适用于那些需求相对稳定且明确定义的项目。
迭代模型:
迭代模型强调在多次迭代中开发软件,每次迭代都会增加新的功能或改进已有功能。每个迭代包括需求分析、设计、编码和测试等活动。迭代模型适用于需求不断变化或不明确的项目。
增量模型:
增量模型类似于迭代模型,但每个迭代都是为系统添加新的功能,而不是仅仅对已有功能进行改进。增量模型允许逐步构建系统,每个增量都是可用的子系统。
螺旋模型:
螺旋模型(Spiral Model):1986 年 Barry Boehm 提出,迭代+渐进式,核心是把风险管理贯穿整个开发过程。每次迭代四步:
- 计划:定目标、约束、风险分析、资源规划(预算/进度/人员)
- 工程:需求分析、设计、编码、测试、集成 → 产出新版本
- 评审和风险分析:评估已完成工作、识别风险、定下一步
- 演示:展示部分功能,收集用户/利益相关者反馈
优点:强调风险管理(早发现早解决)、灵活适应需求变化、用户参与度高。
适用:复杂项目、需求多变、风险高、需紧密监控的项目;代价是多次迭代带来更多成本和时间。
敏捷方法:
敏捷方法是一种迭代和适应性的软件开发方法,强调合作、快速交付和不断改进。它允许在项目的不同阶段灵活地调整需求和优先级。
原则:敏捷方法包括一系列原则,如个体和互动胜过流程和工具、可工作的软件胜过详尽的文档、客户合作胜过合同谈判等。
迭代开发:敏捷方法通常将开发过程分解为短周期的迭代,每个迭代通常持续2至4周,开发团队在每个迭代中交付部分功能。
变更容忍性:敏捷方法更易适应需求变更,因为它鼓励与利益相关方的频繁互动和反馈。
Scrum 和Kanban:敏捷开发方法包括多种实践,如Scrum和Kanban,它们提供了指导开发团队如何组织工作和迭代。
V模型(V-Model):
V模型与瀑布模型有些类似,但它强调在每个开发阶段之后有相应的测试阶段。每个开发阶段都与测试阶段相对应,确保系统满足规范和需求。
快速应用开发(RAD):
快速应用开发是一种加速系统开发的方法,通常涉及原型开发、迭代和用户参与。它旨在快速生成原型,并在用户的反馈下迭代改进。
软件定义
可行性分析
可行性分析(Feasibility Analysis):评估计划的软件项目是否值得做、能不能做。评估维度:
- 技术可行性:有没有足够的技术能力和资源(硬件、软件、框架、工具)
- 经济可行性:预算内能否完成——成本估算、资源需求、预期收益、投资回报率
- 操作可行性:实施后组织是否有足够资源/技能/流程来运行维护使用
- 法律合规:是否符合法律法规和知识产权(数据隐私等)
- 时间可行性:能否按计划和时间表交付
- 市场可行性:是否满足市场需求、有足够市场潜力
结论可能是"可行"或"不可行":不可行 → 重新评估或放弃。目的就是别把资源浪费在无望的项目上。
模型
系统流程图
描述系统各组成部分之间的交互和信息流动(子系统、模块、数据流、控制流),给出系统运作的高层次概览。常见要素:
- 模块/子系统:用矩形(框)表示一个功能单元,带描述性标签
- 数据流:箭头表示数据在系统内部和模块间的传递方向
- 控制流:线条表示控制信号/指令的传递(常以虚线/实线区分)
- 决策和条件:菱形表示条件判断,按不同条件走不同路径
- 开始/结束点:开始常为圆形,结束常为椭圆形
- 并行流程:表示多个模块或操作同时进行
用途:需求分析、系统设计、文档编制——让工程师、项目经理对系统整体结构一目了然。
数据流图DFD
(Data Flow Diagram,DFD)描述系统中数据如何流动和被处理,用于分析信息处理系统的功能和流程。四种基本成分:
- 过程(Process):系统的功能/操作——接收输入数据流,处理后输出;圆形/椭圆形 + 名称(如"订单处理")
- 数据流(Data Flow):流动的数据,箭头方向=流动方向;分外部数据流(与外部实体交互)和内部数据流
- 数据存储(Data Store):数据存储/数据库;矩形(有一条卷曲边)+ 名称(如"客户数据库")
- 外部实体(External Entity):与系统交互的外部参与者;矩形 + 名称(如"客户")
基本思想:数据从外部实体进入系统 → 经过一系列过程和数据存储 → 返回外部实体。用层次结构分解复杂性:从顶层上下文图开始,逐层细化为低层子系统图,便于在不同抽象级别分析设计。
""Structured Analysis" 结构化分析方法
数据字典
数据字典(Data Dictionary DD)是结构化分析的又一有力工具 数据流图描述了系统的分解 但没有对图中的各个成分进行说明 数据字典是为数据流图中的每个数据流、数据储存、数据处理以及组成数据流或文件的数据项做出说明 数据字典的作用是在软件分析和设计过程提供数据描述 是数据流必不可少的辅助资料 数据流和数据字典共同构成系统的逻辑模型 二者缺一不可
数据字典是一个详细的数据库和数据存储结构的目录或索引,是关于数据信息的集合,是数据流图中所有元素的定义的集合,其中包含了有关数据元素、表、字段、数据类型和其它数据相关信息的描述。
数据字典用于记录和管理系统中使用的数据,以确保数据的一致性、完整性和可理解性。它为开发人员提供了数据定义和参考。
状态转换图
状态转换图(State Transition Diagram)是用于描述系统中各种对象或实体的状态及其状态之间的转换的图形工具。
用于建模系统中特定对象的行为和状态变化,通常用于描述有限状态机和自动控制系统。
实体关系图(Entity-Relationship Diagram,ERD):
ERD是用于描述系统中的实体(通常是数据库中的表)以及它们之间的关系的图形表示工具。
ERD用于可视化数据库结构,标识实体、属性和关系,有助于数据库设计和数据模型的理解。
这些建模工具在不同方面的软件工程过程中有不同的应用,用于帮助开发团队更好地理解、分析和设计系统。数据字典有助于数据管理和一致性,实体关系图有助于数据库设计,数据流图有助于流程分析,状态转换图有助于建模对象的行为。根据项目的需求和复杂性,可以选择使用这些工具的一个或多个来支持软件开发过程。
成本-效益分析
成本效益分析(Cost-Benefit Analysis):比较成本和收益,确定项目/投资是否值得。要点:
- 数据收集:直接成本(设备、人力、材料)+ 间接成本(维护、培训、运营);直接收益(销售收入、节省成本)+ 间接收益(声誉、降风险)
- 时效性:考虑时间价值——未来的成本和收益用适当贴现率折算成今天的价值
- 比较:常用指标净现值 NPV(未来收益 − 未来成本的总和);NPV>0 → 经济上可行
- 敏感性分析:测结果对关键参数变化的敏感程度,应对不确定性
COCOMO(Constructive Cost Model,构造性成本模型):基于历史数据和项目参数,估算软件开发项目的成本、资源和时间的经验模型。
Putnam 成本估算模型:把软件开发看作一个具有一定规模和复杂性的工程项目来估算。
需求分析
软件本质是为了实现用户需求 如果曲解了需求 做的再好也无济于事 所以首先就要确定好 到底要做什么 在这个过程中 要采取有效的沟通技术 且须对分析的结果严格审查验证 相较于后期的修复成本 在此阶段的修复成本是非常低的 更凸显了需求分析的重要性 当然 需求分析的最终阶段性结果是软件需求规格说明书
一般来说 需求分析可划分为需求获取 分析建模 需求描述 需求验证4阶段
需求获取:
从项目的相关方(如用户、客户、领域专家)中获取有关他们期望的软件系统功能、性能、约束和期望的过程。这通常包括对话、会议、访谈、问卷调查和观察等方式。
需求获取是需求工程的起始点,它确保开发团队了解用户的需求和期望,以便构建一个满足这些需求的软件系统
结构化需求分析(SA)中 有三种方式获取需求:访谈、简易的应用规格说明技术、快速原型法(P71)
需求分析与建模:
将从需求获取阶段获取的信息进行整理、分类和分析的过程。涉及使用不同的建模工具和技术来表示需求,如数据流图、用例图、状态图、系统流程图、实体联系图、类间关系图
需求分析与建模有助于理清需求的结构,识别需求之间的关系,确保需求的完整性和一致性,以及帮助团队更好地理解项目的范围和复杂性。
需求描述:
将分析和建模结果转化为可验证的文档,通常包括需求规格文档、用例规约、功能规范等。这些文档清晰地描述了软件系统的各个方面,包括功能、性能、接口、安全性等。
是项目团队理解和实现需求的基础,它提供了一个明确的参考框架,确保团队和相关方对需求有一致的理解。
需求验证:
确保需求描述中的需求符合相关方的期望和项目的目标的过程。这通常涉及与相关方进行会议、评审、确认和验证活动,以确保需求的正确性和可满足性。
有助于消除潜在的需求错误和不一致性,确保软件开发项目以正确的方式开始,并减少项目后期的修改成本。
功能需求/非功能需求
- 功能需求:描述系统必须做什么——具体任务、功能和操作(响应用户输入、处理数据、执行计算等)。例:邮件应用中"用户能创建/发送邮件"。描述方式:用例模型、功能规范、用户故事
- 非功能需求:描述系统做得怎么样——质量、性能、安全性、可用性等额外要求。例:性能(响应时间、吞吐量)、安全(数据加密、访问控制)、可用性(可靠性、可维护性)。描述方式:规范、指南、性能指标、安全策略——通常以度量标准和约束条件定义
面向对象分析
(Object-Oriented Analysis,OOA):以对象、类、关系、行为为核心对系统需求建模——把系统的各个方面抽象为对象,识别实体及其关系,定义属性与行为。步骤:
- 需求获取:与利益相关方合作收集需求和期望
- 问题领域建模:把需求转成对象/类/关系——类图、用例图、时序图
- 分析类和对象:确定系统中的重要类/对象,定义属性和行为
- 关系建模:确定对象间关系(继承、关联、依赖)
- 行为建模:状态图、活动图、时序图描述对象生命周期和交互
- 验证和确认:与利益相关方确认模型满足需求,再进入面向对象设计
软件开发
概要设计 详细设计 编码 测试
软件设计
在软件开发过程中,软件设计是指在实际编写代码之前,开发人员将系统的功能、结构和行为进行详细规划和描述的阶段。在软件设计阶段,开发人员通常会创建程序的详细描述,包括算法、数据结构、流程、处理逻辑等,以确保软件能够按照预期运行。这个描述对于将问题转化为可执行代码至关重要,因此它通常是软件设计的核心部分。
总体设计(概要设计)
在需求分析取得正式结果的基础上开展的软件开发工作 是软件开发时期的第一阶段工作 对开发时期的其他后继工作具有统筹作用(需求分析后,详细设计前)
在概要设计中,系统的整体结构和组件之间的关系被定义,但不涉及具体的算法、数据结构或编程语言。这一阶段主要关注系统的高层次结构,包括模块划分、主要组件、交互方式和数据流。概要设计的目标是为详细设计提供一个框架,使开发人员能够更好地理解系统的整体架构。
两个阶段:系统设计阶段:确定系统的具体实现方案;结构设计阶段:确定软件的结构
九个步骤:设想供选择的方案 选取合理的方案 推荐最佳方案 功能分解 设计软件结构 数据库设计 制定测试计划 编写文档 审查和复审
模块化设计:
模块化设计:把系统分解成独立的模块/组件,每个模块负责特定功能,可独立开发、测试、维护。原则:
- 抽象:功能分解为独立任务和子功能,每个模块负责一个明确定义的功能
- 接口定义:清晰的输入/输出/数据结构,便于模块间通信集成
- 独立性:模块尽可能独立,不过分依赖其他模块内部细节
- 封装:内部实现细节封装起来,只暴露必要接口
- 单一职责:一个模块一个职责
- 信息隐藏:隐藏内部实现,只暴露对外所需信息
耦合
耦合(Coupling)= 模块之间相互依赖的程度——联系越紧密越难重用、维护、理解。目标是降低耦合。
常见类型(从低到高,考点):
- 数据耦合:仅通过参数传递数据,不影响内部逻辑——最弱(优)
- 控制耦合:通过控制参数/变量影响另一个模块的行为——较紧密
- 内容耦合:直接访问另一模块的内部数据或实现细节——最紧密,应避免
(另有:非直接耦合 < 标记耦合 < 外部耦合 < 公共耦合,程度介于其间)
- 松散耦合:设计原则——模块间独立、接口互操作,易于替换/重用/理解
- 紧密耦合:依赖性很高,一处改动牵连他处 → 脆弱、难维护
内聚
内聚(Cohesion)= 模块内部各元素的相关性和功能一致性。高内聚 = 模块内元素紧密关联、共同完成一个明确定义的任务。
七个级别(从低到高,考点):
- 偶然(巧合)内聚:元素间没有实质联系,只是偶然凑在一个模块里——最低
- 逻辑内聚:把逻辑上相似的几个功能放进一个模块,由传入的标志参数决定执行哪个(如一个模块处理所有类型的打印/输出)
- 时间内聚:各任务在同一时间段内执行但功能不相关(如初始化模块:置初值、开文件、发邮件、写日志一起做)
- 过程内聚:元素按固定的过程次序执行,但功能关联较弱
- 通信内聚:各元素操作同一数据(对相同输入数据处理/产生相同输出),通过全局数据结构通信
- 顺序内聚:前一元素的输出正是后一元素的输入,形成处理链条
- 功能内聚:所有元素共同完成单一功能——最高、最理想
口诀级记忆:高内聚、低耦合相辅相成——高内聚让模块内部紧凑(易测试、易修改、职责单一),低耦合让模块之间独立(易替换、易重用、互不牵连)。两者一起构成模块化设计的核心。
准则_概念(深度宽度扇入扇出)
深度 (Depth):
"深度"通常指的是软件结构中的层次结构或嵌套层次的深度。它表示一个模块、类、或函数调用链中的嵌套层数。较深的结构可能表明复杂性或多层次的依赖关系。
宽度 (Width):
"宽度"指的是在软件结构中模块、类、或函数之间的直接连接或依赖的数量。它表示一个模块或类与其他模块或类之间的直接关系。较宽的结构可能表明有多个组件直接相互作用。
扇入 (Fan-In):
"扇入"表示一个模块或函数被多少个其他模块或函数直接调用。它衡量了一个模块的复用程度和模块之间的依赖性。高扇入表示模块在多个地方被重复使用。
扇出 (Fan-Out):
"扇出"表示一个模块或函数直接调用多少个其他模块或函数。它衡量了一个模块的复杂性和其对其他模块的依赖。高扇出可能表明模块的责任过多或复杂。
详细设计
详细设计阶段是在概要设计之后,直接面向编程和实施的阶段。
在详细设计中,概要设计的框架被细化,具体的算法、数据结构和编程语言的细节被确定。这一阶段涉及编程接口、函数和方法的定义,以及数据库架构、用户界面设计等具体实现细节。
详细设计的目标是为开发人员提供足够的信息,以便他们能够编写和测试实际的软件代码。
在概要设计和详细设计之间,设计师将系统的高级概念转化为具体的实现计划。这两个阶段是迭代的,通常需要多次调整和改进,以确保最终的软件系统满足用户需求,并且具有良好的质量和性能。概要设计关注系统的结构,而详细设计关注实现细节。
主要任务有六方面:
为每个模块进行详细的算法设计 确定算法 选择适当的工具表达算法的过程
对模块内的数据结构进行设计
对数据库进行物理设计
根据软件系统的类型 可能进行代码设计 网络系统设计 输入输出格式设计 系统配置设计 人机对话设计等
编写详细设计说明书
评审
工具
详细设计阶段通常使用各种工具和图形表示来帮助设计人员清晰地表达设计思路和决策。
结构图(Structure Chart "SC图" )用于软件设计和分析的图形表示方法,用于展示软件系统的模块组织和结构。通常采用层次结构的方式来表示模块之间的依赖关系和组织结构。
程序流程图 (Flowchart):
程序流程图是一种图形化表示方法,用于展示算法、流程和决策的逻辑结构。它包括各种流程框、连接线和决策框,有助于描述软件的操作流程。
IPO (Input、Process、Output)
用于概括和描述软件系统的功能,通常在需求分析和设计阶段使用。它有助于理解软件系统的输入和输出流程,以及核心的处理逻辑。这个模型可以用于识别系统的功能需求,规划软件的处理逻辑,并定义系统的交互和接口。
Input (输入):表示软件系统接受的外部数据、信息或信号。输入通常是系统接收和处理的原始数据,可以来自用户、其他系统、传感器等。输入是软件系统开始处理的起点。
Process (处理):表示软件系统的核心逻辑和算法,用于处理输入数据以执行特定任务或功能。处理包括数据的计算、操作、变换和控制,以满足系统的要求。
Output (输出):表示软件系统生成的结果、响应或产出。输出是处理后的数据或信息,它通常是系统向用户、其他系统或设备提供的最终结果。
PAD图 (Program Action Diagram):
PAD图是一种图形化表示方法,用于描述程序或模块内部的操作流程。它包括动作框、流程线和决策框,有助于展示程序的内部操作。
程序设计语言 (PDL - Program Design Language):
PDL 是一种用于描述程序逻辑的高级伪代码语言。它可以帮助设计人员编写可读性强的设计文档,详细说明软件的功能和逻辑。
盒图 (Box Diagram):
盒图是一种图形表示,用于表示模块、函数或类的内部结构。每个盒子代表一个模块,内部包含输入、处理和输出等信息,有助于模块设计。
判定表 (Decision Table):
判定表是一种表示软件中复杂决策逻辑的方法。它将不同条件和操作映射到表格中,以便设计人员更容易理解和实现复杂的决策逻辑。
判定树 (Decision Tree):
判定树是另一种表示决策逻辑的图形方法,通过树状结构展示不同条件和操作之间的关系,有助于可视化决策流程。
这些工具和图形表示方法可根据设计任务的需要选择。它们有助于设计人员更清晰地表达软件的设计思路,使其他团队成员能够理解和实施设计。此外,这些工具还有助于内部审查和评审,以确保设计的质量和一致性。在详细设计阶段,使用适当的工具可以提高设计的可理解性和可维护性。
面向数据结构设计方法(Jackson)
Jackson Structured Programming:Michael A. Jackson 提出,强调数据结构对软件设计的关键性——先定义数据结构,再推导处理过程。关键原则:
- 数据结构优先:首先定义数据结构(类型、记录、数组等),清晰表示数据
- 逐步细化:从高层数据结构逐步深入到具体细节
- 数据结构图表:用图表描述数据结构及相互关系
- 数据结构约束:明确定义约束和不变性,保证一致性完整性
- 分层结构:高层表示概念信息,底层表示物理存储细节
- 支持自顶向下(总体架构)和自底向上(底层细节)两种方式
软件实现
编码和测试
编程语言:选择合适的编程语言。
编码标准和最佳实践:遵循良好的编码规范,提高代码质量。
软件测试:编写测试用例以验证代码。
软件测试
在产品投入运行前 对软件需求分析 设计和编码各阶段产品的最终检查 为保证软件开发产品的正确性完全性一致性 从而进行检测错误和修正错误的过程
软件测试的过程就是发现并改正软件缺陷的过程
测试方式
按测试方式分:静态测试和动态测试。
- 动态测试(Dynamic Testing):实际运行软件——执行测试用例、输入数据、观察响应,比较实际结果与预期结果。包括单元、集成、系统、性能、安全测试等
- 静态测试(Static Testing):不运行软件,检查静态属性——代码审查、文档审查、需求审查、静态代码分析、模型检查。在软件运行前(或独立于运行)发现问题
区别一句话:动 = 跑起来验证功能行为;静 = 看代码文档找问题。两者通常配合使用:静态早发现,动态验证运行正确性。
测试方法
按测试方法可以分成白盒测试 黑盒测试 灰盒测试
白盒测试(White Box Testing):
定义:白盒测试是一种测试方法,测试人员了解被测试软件的内部结构、算法和代码,以编写测试用例来验证代码的逻辑正确性。
关注点:白盒测试关注于代码覆盖率、路径覆盖和内部代码的执行。测试人员需要具备开发和编程方面的知识,以设计测试用例来检查代码中的错误和漏洞。
方法:白盒测试通常包括单元测试、集成测试和系统测试,以确保每个代码块和逻辑路径都得到验证。
用例设计
逻辑覆盖、基本路径测试、程序插桩
逻辑覆盖(Logical Coverage):旨在确保代码中的各种逻辑路径都被执行和测试。逻辑路径是代码执行的不同分支或条件情况。
逻辑覆盖通常包括以下类型:
语句覆盖:确保每个代码语句至少执行一次。
判定覆盖:确保每个条件判定至少被测试两次,一次为真,一次为假,以覆盖不同分支。
条件覆盖:确保每个条件表达式的每个可能取值都被测试。
多条件覆盖:确保每个条件判定中的所有可能组合都被测试。
基本路径测试(Basis Path Testing):旨在测试程序中的所有可能路径。每个程序通常可以被分解为基本块和分支,而基本路径测试的目标是覆盖每个可能的基本路径,以确保每一行代码都被执行。这需要深入了解程序的结构,以便识别和测试所有可能的路径。
黑盒测试(Black Box Testing):
定义:黑盒测试是一种测试方法,测试人员不需要了解被测试软件的内部结构,而是基于软件的规范、需求和功能来设计测试用例。
关注点:黑盒测试关注于验证软件的功能、用户界面和对外部输入的响应。测试人员不关心内部代码的执行过程。
方法:黑盒测试包括功能测试、验收测试、性能测试、安全测试等,以确保软件在用户角度下按照预期工作。
用例设计
等价类划分、边界值分析、因果图、决策表、错误推测法、场景法
等价类划分(Equivalence Partitioning):
测试人员将输入数据分为不同的等价类,以确保每个等价类只需测试一次。这样可以减少测试用例的数量,同时确保覆盖了各种可能的输入情况。例如,如果一个输入字段要求输入 1 到 100 之间的数字,那么可以将输入分为三个等价类:小于 1、1 到 100 之间、大于 100。然后为每个等价类选择测试用例。
边界值分析(Boundary Value Analysis):
边界值分析是等价类划分的一种延伸,它侧重于测试输入的边界情况。测试人员选择在等价类的边界上进行测试,以确保系统在边界条件下能够正确处理数据。继续上面的示例,边界值测试将包括输入 1 和 100,以确保系统能够正确处理最小和最大值。
因果图(Cause-Effect Graph):
因果图是一种图形表示,用于捕捉系统的输入和输出之间的因果关系。有助于测试人员理解输入数据对系统行为的影响。使用因果图来生成测试用例,以验证系统对不同输入情况的响应。因果图是一种可视化工具,通常以图形方式呈现,以帮助识别测试需求。
测试过程
在软件测试过程中,通常遵循一种层次化的测试方法,以确保软件系统的质量和可靠性
单元测试:
软件测试的第一阶段。单元测试是软件测试的基本组成部分,旨在测试单个模块、函数或类的功能。单元测试用例针对代码的特定部分,验证它是否按照预期工作。这些测试通常由开发人员编写,用于捕获和修复代码中的错误。
集成测试:
集成测试是在单元测试之后进行的,它涉及测试多个模块或组件之间的交互和集成。用于验证不同模块之间的交互,它确保各个模块在组合时能够正常工作,以构建更大的系统。这些测试可识别模块集成所带来的问题,如接口问题、数据传递问题等。集成测试可以分为逐步增加的方式,逐渐集成和测试不同部分。
系统测试:
系统测试是在集成测试之后进行的。是对整个软件系统进行的测试,以确保整个系统满足其规范和需求。这包括对系统功能、性能、兼容性等进行广泛测试。旨在模拟真实使用环境中的各种情况,以验证系统的稳定性和可靠性。
验收测试:
最后,验收测试是由最终用户或客户执行的测试,目的是确保软件系统符合其需求和期望。验收测试通常是最后的测试阶段,如果系统通过了验收测试,它就可以交付给客户。
路径覆盖/人工检测
- 路径覆盖(Path Coverage):确保程序中每条可能的执行路径都至少被一次测试用例覆盖——检查不同分支、条件和控制流路径。常用于单元测试和白盒测试。需识别所有路径(条件分支、循环、异常处理)并设计用例,可手动或用自动化工具
- 人工检测(Manual Testing):测试人员手动执行测试用例,模拟实际用户的操作和交互(运行程序、输入数据、观察行为)——功能测试、验收测试、UI 测试。常用于集成、系统、验收测试,验证用户角度的可用性
软件调试
测试的目的是充分发现软件的错误信息 调试是在测试完成结果分析后 对结果分析发现的错误进行程序诊断 并且寻求改正的过程
常用五种方法:
试探法 回溯法 对分查找法 归纳法 演绎法
常用五种方法:
- 试探法(蛮力法):根据错误征兆猜测出错的大致位置,在可疑处插入打印语句/断点强行试错——简单粗暴、效率低,适合小程序
- 回溯法:从错误征兆出发,沿程序控制流反向追踪(往回找),直到发现错误根源——只适合小程序;大程序回溯路径太多,会失效
- 对分查找法:在程序中间位置注入关键变量的"正确值",看输出对不对——输出正确 → 错误在前半段,否则在后半段,反复对半缩小错误范围(前提:已知某些关键变量的正确值)
- 归纳法:从错误征兆(线索)出发,整理线索之间的关系、找出规律,推断出错误原因——从个别到一般。步骤:收集有关数据 → 组织数据 → 提出假设 → 验证假设
- 演绎法:先列举出所有可能的原因,用测试数据逐一排除不成立的,对剩下的假设细化验证——从一般到个别。步骤:设想所有可能原因 → 用数据排除 → 细化余下假设 → 验证
⚠️ 注意与数据结构里的"二分查找""回溯算法"区分:这里说的是排错策略,不是通用算法。
质量保障
- 质量标准:定义软件质量的具体标准和规范(性能、可用性、安全性要求等),作为评估比较的基准
- 质量度量:用指标和工具衡量监控质量——代码覆盖率、性能测试结果、缺陷报告等
- 质量控制:确保软件符合质量标准的过程——审查和审计,促使团队遵循最佳实践、解决潜在问题
项目管理
配置管理
版本控制:管理和跟踪软件的不同版本。
- 版本:软件每个演化阶段(用数字、标签或分支标识)
- 分支:为并行开发多个版本/特性而创建的分支线,最后合并回主版本
- 合并:把不同分支/版本的更改整合到统一版本;冲突解决:多人同时改同一处时处理冲突
优势:跟踪变更历史、回滚、多人协作、保证质量。
配置管理工具:支持版本控制和配置管理的软件(Git、Subversion、Mercurial、Perforce 等)——版本跟踪、分支合并、访问控制、与开发环境/CI 集成。
软件配置项
(Software Configuration Item,SCI)
软件配置管理的关键对象:软件工程过程中产生的、可独立进行配置管理的信息项——不同版本、组件、文档、源代码、二进制文件等。每个 SCI 有唯一标识符,用于跟踪变更、回滚版本、保证一致性。
软件配置管理的主要内容:
- 配置项标识和命名:唯一标识符和名称
- 配置项版本控制:记录各版本,可回滚、可查历史
- 配置项状态管理:开发中/测试中/已批准/已发布等状态
- 配置项变更管理:变更请求的审查、批准、实施、验证
- 配置项审查和审计:定期审查,确保符合标准要求
软件维护
软件生存周期最终环节才进行软件维护 维护成本很高 所以开发时要尽量考虑到后期问题
副作用
维护过程还会带来不良影响 即使有设计文档和回归测试 也避免不了副作用的产生。可分为三类:
- 代码副作用:修改/新增源代码,可能对现有行为产生意想不到的影响——小心处理,别改崩现有功能或引入新错误
- 数据副作用:对现有数据的更改(更新数据库记录、改文件格式、修数据错误)——确保数据完整性和一致性
- 文档副作用:代码改了,相关文档/注释/用户手册没跟上 → 文档与代码不一致,带来混乱——改代码必须同步更新文档
维护类型
- 改正性维护:修复已识别的错误/缺陷(崩溃、逻辑错误、性能问题),让软件正常运行
- 适应性维护:适应变化的环境——新硬件、新操作系统、新数据库、新法规要求
- 完善性维护:主动改进——优化性能、代码重构、添加新特性、改进用户界面(占比通常最大)
- 预防性维护:为未来着想——审查分析现有代码,提前消除潜在问题、漏洞、性能瓶颈,减少未来维护成本
结构化维护/非结构化维护
- 结构化维护:有组织、有计划——明确的维护计划与流程(问题报告→分析→修复→测试→发布)、强调文档化、可跟踪可审计、走正式的变更控制和版本管理。更可取,质量和可持续性好
- 非结构化维护:临时性、救火式——缺乏计划、文档不完整、变更不经正式审查。只适合紧急情况或小问题,长期会导致混乱和不可维护
其他
其他
文档
项目章程(Project Charter):
阶段位置:项目启动阶段。
定义:项目章程是项目的正式启动文件,包含项目的业务背景、目标、范围、项目经理的角色和职责,以及项目的批准和授权信息。
用途:确保项目得到正式批准和授权,明确项目的目标和范围。
项目建议书(Project Proposal):
阶段位置:项目前期规划阶段。
定义:项目建议书是项目的初期文件,提出项目的概念和目标,包括项目的背景、目标、范围、预期成果、资源需求和预算估算。
用途:获得初步批准和支持,帮助明确项目的方向和可行性。
软件项目计划(Software Project Plan):
阶段位置:项目前期规划或项目执行阶段的早期。
定义:软件项目计划是用于规划和管理软件项目的详细计划,包括时间表、资源分配、任务分配、风险管理计划等。
用途:指导项目的执行和监控,确保项目按计划进行。
项目/分解
项目范围(Project Scope):
定义:项目范围是指项目的边界和包含的所有工作、交付物和目标。它定义了项目的规模、目标和可交付成果。
重要性:明确定义项目范围对于确保项目成功至关重要。它有助于防止范围蔓延、项目变更和不明确的目标。
过程:项目范围的管理包括范围规划、范围定义、范围创建、范围验证和范围控制。
WBS(Work Breakdown Structure,工作分解结构):把项目分解为可管理的任务、子任务和工作包的分层结构——识别主要阶段/子项目/任务,组织成层次树,便于分配、管理、监控。常用创建方法:
- 自上而下法(最常用):从高级任务和阶段开始逐步细分
- 自下而上法:从具体任务开始逐级汇总成大组件
- 参与式方法:团队通过会议/工作坊共同讨论确定结构
- 模板方法:用现成 WBS 模板定制
- 产品导向法:从最终交付物倒推所需任务
- 阶段划分法:按阶段各自建 WBS(适合复杂项目)
- 专家划分法:请专家/资深项目经理指导
- 标杆对比法:参照类似项目的 WBS
任务分解(Task Decomposition):
定义:任务分解是将项目的高级任务、子任务和工作包进一步细分为更小的任务或步骤的过程。这有助于明确每项任务的具体工作和责任。
重要性:任务分解是实施 WBS 的关键步骤,它确保项目工作被细化为具体的工作任务,以便团队成员理解和执行。
过程:任务分解涉及将大型任务分解为更小、可管理的子任务,定义每项任务的范围、资源需求和时间估算。
范围变更(Scope Change):
定义:范围变更是指项目范围的任何更改,包括向项目中添加新任务、删除现有任务、修改任务的要求或目标,以及调整项目的范围。
原因:范围变更可能是由于客户需求的变化、项目团队的错误、外部因素的干扰或新的发现而引起的。
处理:范围变更需要经过变更控制流程,包括识别、评估、批准和实施。项目经理和相关干系人需要评估变更对项目进度、成本和风险的影响。
范围基线(Scope Baseline):
定义:范围基线是项目的初始范围文档,其中包含了项目的详细范围、目标和可交付成果。它通常包括项目范围说明书、WBS、WBS词典等。
用途:范围基线用于规定项目的范围,作为项目的准则。它有助于项目团队和干系人理解项目的范围,确保一致性和可度量性。
变更:如果出现范围变更,范围基线可能需要进行更新和重新批准。这有助于确保任何范围变更都经过审慎考虑和批准。
💬 评论