UML
UML概述
为什么需要建模
建模是为了理解事物而对事物作出的一种抽象,是对事物的一种通用、明确的书面描述。假如让你建造一栋属于自己的房子,你第一件思考的事情是什么?是思考去哪里买什么材料吗?非也!你一般会先了解建筑的大小、形状,进而做出相应的规划与图纸,甚至模型。如果在规划过程中有更好的想法,还可以不断对图纸和模型进行调整,直至满意后才开始动工。
为什么需要语言
日常生活中,我们都用普通话进行交流,看起来稀疏平常,但是如果存在地域差异的话(如胡建人),那就很容易引起误会或笑话。
在各类编程语言的世界里,大家可以通过编程语言(如Python、Java)所特有的语法进行交流,Linux之父Linus曾说“Talk is cheap. Show me the code.”,代码是程序员最好的沟通工具。但是,身为资深Python程序员的你确定能看得懂神级Java程序员写的代码吗?这时候再Show the code就变得毫无意义了。
UML由来
面向过程把世界看作是由一个个相互关联的小系统组成,每个小系统都有着明确的开始和明确的结束,开始和结束之间有着严谨的因果关系。常见的面向过程编程语言有C、Fortran、VBScript等。
HTML、Markdown、CSS等“语言”在大多数程序员眼中并不属于编程语言,因为其仅仅作为对文本的扩展,并没有严谨的语法和逻辑处理能力。
面向对象是把世界看作是一个个相互独立的对象,相互之间并无因果关系,它们平时是“老死不相往来”。只有在某种外部力量的驱动下,对象之间才会依据某种规律相互传递信息。常见的面向对象编程语言有Java、Python、PHP、JavaScript等。
面向对象的兴起提供了一种新的思维模式,一种关于计算机与信息结构的新思维。由于当时面向对象还处于比较新颖的阶段,分析方法百花齐放。面向对象分析(OOA)是建立于以前的信息建模技术基础之上从问题中发现类和对象的概念来考察需求的分析方法。面向对象设计(OOD)把焦点从问题转移到了了解空间,包含对设计系统的逻辑与物理过程的描述,以及静态和动态模型的设计。
OOA与OOD衍生出许多不同流派的方法论,这样非常不利于软件工程师的交流,阻碍了计算机的快速发展。为了统一各种建模方法,UML被批准成为标准建模语言。
UML定义
UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明、可视化、和编制文档的一种标准语言。
UML的目标是尽可能简单的同时能够对实际需要建立的系统的各个方面建模。UML有足够的表达能力以处理现代系统的所有概念,譬如并发和分布式,以及软件工程中使用的技巧,如封装和组件。
UML元素
UML事物
类
类是指具有相同属性、方法、关系和语义的对象的集合。类在UML中,第一个框是类的名称,第二个框是属性,第三个框是方法名。
接口
接口是指类或组件所提供的服务,描述了类或组件对外可见的动作。接口在UML中,第一个框是类的名称,第二个框是方法名。
组件
组件描述软件组件与组件之间的关系,组件反映了代码的物理模块,显示了代码的结构。一个组件应当是一个独立的业务模块,有着完备的功能,可独立部署,一个组件可以看成是一个完备的服务。动态链接库(DLL)、子系统(定位子系统、前端)都可以被认为是组件。
节点
节点被定义为在运行时存在的物理元素。
状态
状态由一系列对象的状态组成,它是有用的,一个对象在其生命周期的状态是很重要的。
包
封装是唯一一个分组事物可收集结构和行为的东西,简单来说,包就像一个“文件夹”,把文件“代码”组织起来。
UML关系
UML的关系以类关系为主,本章节主要介绍的关系主要是类相关的。在UML类图中,描述类的内部结构和类与类之间的关系有: 泛化、实现、关联、聚合、组合、依赖。
关系的强弱顺序:泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖。
泛化
泛化表示 is-a 的关系,是继承的关系,子类继承父类,子接口继承父接口。Tester is a Person 表示 Tester 继承自 Person,Person是父类,Tester是子类。
实现
一个class类实现interface接口(可以是多个)的功能,实现是类与接口之间最常见的关系。
依赖
依赖是指一个类使用(use)另一个引用B(变量或类或函数等)作为参数,这种关系具有偶然性、临时性。但B的变化会影响到A,比如Tester实例要写测试报告,需要使用电脑,此时Tester实例与电脑的关系就是依赖。
关联
关联是一种拥有的关系,它使一个类知道另一个类的属性和方法。关联的关系既可以是单向也可以是双向。Tester实例一般都有自己的测试账号Account,而Account都会记录Tester实例的信息。关联也包括聚合和组合关系。
聚合
聚合表示has-a的关系,是一种不稳定的包含关系。较强于一般关联,有整体与局部的关系,并且没有了整体,局部也可单独存在。在类图使用空心的菱形表示,菱形从局部指向整体。譬如测试人员都有工具来协助提升测试效率。
组合
表示contains-a的关系,是一种强烈的包含关系。组合类负责被组合类的生命周期,是一种更强的聚合关系。部分不能脱离整体存在。在类图使用实心的菱形表示,菱形从局部指向整体。譬如人类都是由细胞组成。
UML图
类图
类图Class Diagram通过显示出系统的类以及这些类之间的关系来表示系统。类图是静态的,它显示出什么可以产生影响但不会告诉你什么时候产生影响。类图显示集合的类,接口,关联,协作和约束,它也被称为作为结构图。
概述
类图(Class diagram)是显示模型的静态结构,特别是模型中存在的类、类的内部结构以及它们与其他类的关系等。类图不显示暂时性的信息。类图是面向对象建模的主要组成部分。它既用于应用程序的系统分类的一般概念建模,也用于详细建模,将模型转换成编程代码。
类图概览
类的组成元素
一个类由3部分组成:类名、属性和方法:
在面向对象的语言里,常使用protected/private/public等对类成员进行可访问性的修饰,对应到PlantUML中,其符号及图表关系如下:
定义类
使用 class 关键字进行类的定义,并在花括号内进行 属性 及 方法的设置。
class Tester {
-String private_field
#int protected_field
~char package_private_field
+char[] public_field
-void private_method()
#void protected_method()
~int package_private_method()
+BeTester public_method()
}
实例UML代码
@startuml
工程师 <|.. 软件工程师 : 实现
软件工程师 <|-- 测试工程师 : 继承(泛化)
软件工程师 <|-- 开发工程师 : 继承(泛化)
测试工程师 *-- 测试思维 : contains(组合)
测试工程师 *-- 测试技术 : contains(组合)
开发工程师 o-- 头发 : has(聚合)
开发工程师 <--> 身份证 : 关联
开发工程师 ..> IDE : 使用(依赖)
@enduml
UML图
类图解析
泛化(继承)
泛化实际上是继承关系,是对某一细分领域的划分。譬如 测试工程师 和 开发工程师 都是软件工程师的子类。PlantUML中语法为:
父类 <|-- 子类
实现
实现是对抽象概念的具体化说明,抽象的类或接口并不会对其内部方法进行编码实现,而是通过具体的类来对对该抽象类或接口进行编码。譬如 工程师 是一个抽象,软件工程师就是对工程师的具体化说明。PlantUML中语法为:
接口/抽象类 <|.. 类
依赖(使用)
依赖表示对象在运行期间会使用到另一个对象。譬如 开发工程师 在编码时会使用到 IDE工具。PlantUML中的语法为:
类 ..> 工具
关联(拥有,成员变量)
关联关系是一种拥有的关系,它使一个类知道另一个类的属性和方法。譬如 开发工程师拥有一头乌黑的秀发。PlantUML中的语法为:
类 <--> 类
聚合(整体的一部分)
聚合关系表示整体与部分的弱依赖关系,若整体不存在了,部分依然可以存在。譬如 软件工程师 与 公司的关系,公司不存在了,软件工程师依然存在。PlantUML中的语法为:
类 *-- 类
组合(由..组成)
组合关系表示整体与部分的强依赖关系,弱整体不存在了,部分也不存在。譬如 测试部门 与 公司的关系,公司不存在了,测试部门也就消失了。在比如 测试思维与测试工程师,当工程师不存在了,那么测试思维也就不在了。PlantUML中的语法为:
类 o-- 类
- 实线比虚线关系强
- 实心比空心关系强
- 三角最稳(泛化/实现) > 四边形(聚合/组合) > 箭头(关联/依赖)
其他操作
添加注释
class Tester
note left: 这是在左侧的注释信息
class Tester
note right: 这是在右侧的注释信息
class Tester
note top: 这是在右侧的注释信息
class Tester
note bottom: 这是在右侧的注释信息
定义接口和抽象类
abstract class 工程师
interface 工具箱
改变箭头方向
A -left-> B
C -right-> D
E -up-> F
G -down-> H
除了 → 以外, ..> 、 <|— 、 *— 、 o— 等含方向的线段都可以使用方位关键字。
对象图
对象图和类图一样反映系统的静态过程,但它是从实际的或原型化的情景来表达的。对象图显示某时刻对象和对象之间的关系。由于对象存在生命周期,因此对象图只能在系统某一时间段存在。
概述
对象图(Object Diagram)是类的实例化对象的关系图。对象图与类图使用相同的UML元素组成。不同之处在于,对象图中可以显示一个类的多个实例化对象。
一个对象图是类图的一个实例,由于对象存在生命周期,对象图描述的是某一个时刻(或某一时间段)对象的存在关系图。
软件系统里的类图是有限的,但是由于对象的生命周期的多变性,我们可以绘制出无数个系统的对象图。
由于对象是对类的实例化,对象之间是不存在实现的关系。
意义
对象图作为软件系统在某一时刻或某一时间段内的快照,是类图的实例化及其关系的静态写照,不能能让我们更详尽地了解系统的各种状态,并且也更容易发现系统中的有效状态与无效状态。
实例
@startuml
object 小静_测试工程师 {
name = "小静"
}
object 逆向思维_测试思维 {
name = "逆向思维"
}
object 测试设计_测试技术 {
name = "测试设计"
}
object 小鹏_开发工程师 {
name = "小鹏"
}
object 44xxx_身份证 {
id = "44xxxxxxxxx"
}
object VSCODE_IDE {
name = "VS Code"
}
object 大波浪_头发 {
type = "大波浪"
}
小静_测试工程师 o-- 逆向思维_测试思维
小静_测试工程师 o-- 测试设计_测试技术
小鹏_开发工程师 ..> VSCODE_IDE
小鹏_开发工程师 <--> 44xxx_身份证
小鹏_开发工程师 *-- 大波浪_头发
@enduml
实例说明
- 小静 是 测试工程师的实例。
- 小静 掌握 逆向思维 和 测试设计。
- 小鹏 是 开发工程师的实例。
- 小鹏 的 身份证是 44xxxxx。
- 小鹏 使用 VS Code作为开发工具。
- 小鹏 拥有 大波浪发型的头发。
类图与对象图的对比
用例图
用例图描述了作为一个外部的观察者的视角对系统的印象,强调这个系统是什么而不是这个系统怎么工作。用例图与情节紧紧相关的,情节scenario是指当某个人与系统进行互动时发生的情况。
前言
当很多测试工程师谈及用例时,会默认 用例 = 测试用例 。但这是非常片面的理解,因为在软件工程领域,Use Case(用例)和 Test Case(测试用例)是完全不同的概念。
概述
当我们要弄清楚需求时,往往使用5W2H方法协助分析,其中Who和What的问题可以通过用例图来解决。
- 这个系统谁在用?
- 这些人通过这个系统能做什么?
5W2H又叫七问分析法,为发现解决问题的线索提供思路。通常的5W2H分别为:What/Who/When/Where/Why 和 How/How Much。
用例图(Use Case Diagram)是描述用例、参与者以及它们之间关系的图。
用例是外部可见的系统功能,即用户可感知到的功能,文章下面讲到。
用例图是从用户的角度来描述对信息系统的需求,分析产品的功能和行为。
用例图是系统的蓝图,呈现参与者,用例,以及它们之间的关系,主要用于对系统、子系统或类的功能行为进行建模。
用例图元素
用例图有三个部分:参与者(Actor)、用例(Use Case) 和 关系。
参与者(Actor)
参与者是对系统使用者的抽象。参与者是与系统交互的人或另一个系统,如果是人可以称为“角色”。在分析系统时,应该先思考什么角色会用这个系统,然后逐一思考不同的角色对系统有什么需求。
在UML中,通常使用以下表示方法:
actor 测试工程师 as te
在UML中,参与者一般使用人形图案来表示,参与者不仅限于人,还可以是外部交互系统。
用例
用例是外部可见的系统功能,对系统提供的服务进行描述。用例通常使用动宾结构(动词+名词)来描述,如 编写测试用例、编写代码 等描述来说明用例。每个用例提供了一个或多个场景,该场景说明了系统是如何与最终用户或其它系统互动,也就是谁可以用系统做什么,从而获得一个明确的业务目标。
在UML中,通常使用以下表示方法(括号):
te --> (编写测试用例)
在UML中,用例使用一个椭圆形来表示,使用 (Use Case Name) 表示
关系
用例图中常用关系有:参与者的继承、关联、泛化、包含(include)、扩展(extend)。
关联(Association):线条是指参与者与用例之间线条,有三种:无箭头,指向用例的箭头,指向执行者的箭头。一般来说,箭头的尾部用来表示启动交互的一方,头部用来表示被启动的一方。
包含
包含关系描述的是一个用例需要某种功能,而该功能被另外一个用例定义,那么在用例的执行过程中,就可以调用已经定义好的用例。表示符号:<< include >> 。通常用 基用例 表示包。
@startuml
(设计测试用例) --> (分析需求) : <<include>>
(设计测试用例) --> (分析测试点) : <<include>>
(设计测试用例) --> (建立模型) : <<include>>
(设计测试用例) --> (编写测试用例) : <<include>>
@enduml
泛化
子用例继承了父用例所有的结构、行为和关系,是父用例的一种特殊形式。
@startuml
actor 测试工程师 as te
te --> (执行测试用例)
(执行测试用例) <|-- (执行功能测试用例)
(执行测试用例) <|-- (执行性能测试用例)
@enduml
扩展
用一个用例(可选)扩展另一个用例(基本例)的功能,将一些常规的动作放在一个基本用例中,将可选的或只在特定条件下才执行的动作放在它的扩展用例中。表示符号:<< extend >>。
actor 测试工程师 as te
te --> (执行测试用例)
(执行测试用例) <.. (提交Bug) : <<extend>>
顺序图
顺序图将交互关系表示为一个二维图。纵向是时间轴,时间沿竖线向下延伸。横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时,角色用一条虚线表示,当对象的过程处于激活状态时,生命线是一个双道线。消息用从一个对象的生命线到另一个对象生命线的箭头表示。
概述
顺序图(Sequence Diagram),也叫时序图,简而言之就是描述参与者或子系统之间自上而下(时间维度)的交互。交互主要通过对象之间发送消息来实现。顺序图也可以用来展示出用例图的行为顺序,当参与者执行/触发一个用例时,都会有一条消息从触发者发送给接收者,从而引起状态转换。
因为顺序图是按照时间顺序现实对象之间的交互,所以顺序图只能应用于顺序逻辑中,对于并发、异步等场景显得无能为力。
顺序图元素
顺序图有四部分:参与者(Actor)或对象(Object)、生命线(Lift Line) 、激活期 和 消息。
参与者(Actor) / 对象(Object)
参与者与对象按照一定顺序从做到右排列。UML中并没有对排列顺序作出任何要求,但是经过长期的积累得出以下经验:
- 活动的起始点放在最左侧。
- 交互频繁的参与者或对象靠拢。
在UML中,参与者通常使用以下表示方法:
actor 测试工程师 as te
或
participant 用例系统 as tcms
在UML中,对于参与者或对象,我们可以使用 as 来给对象起别名,方便后面的引用。
除了使用 actor 和 participant 声明参与者和对象外,还可以通过 boundary、control、entity 和 database 来声明,仅图标差异。
生命线
每个参与者或对象都有生命线,生命线随着参与者的创建而产生,销毁而小时。当创建了参与者后,UML图上会顶部和底部各显示参与者,并且通过垂直虚线相连,这条垂直虚线就是生命线。
激活期
激活期是指对象在整个活动中获得了焦点,需要一段时间来执行某个动作,在UML图中是一个空心的矩形表示,其语法为:
activate te
激活期是一个时间段,有开始就必要会结束,结束的语法为:
deactivate te
在activate和deactivate之间就形成一个矩形,这就是激活期。
消息
对象之间的交互是通过相互发消息来实现的。一个对象通过发送消息请求另一个对象做事件。
消息从源对象指向目标对象。消息一旦发送便将控制从源对象转移到目标对象。
消息不仅可以从A对象发给B对象,还可以自己发给自己。
te -> dev : 提了个bug,赶紧解
activate dev
dev -> dev : 改bug中
dev --> te : 改完了,麻烦回归一下
deactivate dev
消息可以分为同步消息、异步消息以及返回消息。
同步消息
直到等待接收者返回消息,譬如 测试工程师 准备写测试用例,发了消息“给我需求文档”给产品经理,只有等待产品经理返回消息后,测试工程师才可以继续后续的操作。
在UML中,使用实心箭头
te -> pm : 需求文档
异步消息
无需等待,发送消息后继续操作。譬如 测试工程师 拿到需求文档后,发消息“给我详细设计文档”给 开发工程师,此时测试工程师不需要等开发工程师给详设文档,在开发准备的过程中进行验收用例设计。
在UML中,使用空心箭头
te ->> dev : 详设文档
返回消息
表示完成某个活动或动作后,给予消息源反馈内容。
在UML中,使用空心箭头
dev --> te : 详设文档
顺序图操作
顺序图标题
通过 title 关键字为顺序图设定名字。
@startuml
title Bug简易流程
te -> dev : 提了个bug,赶紧解
activate dev
dev -> dev : 改bug中
dev --> te : 改完了,麻烦回归一下
deactivate dev
@enduml
分割线
使用分割线可以把一个顺序图划分为不同的阶段。分割线使用 == 阶段名称 ==
的形式来表示。
@startuml
actor 测试工程师 as te
actor 开发工程师 as dev
participant 用例系统 as tcms
== 测试阶段 ==
== 改bug阶段 ==
== 回归阶段 ==
@enduml
注释
在UML图中描述的内容有限,需要通过注释配合说明才能达到更好的效果。
一个消息只能对应一个注释信息。
@startuml
te -> dev : 提了个bug,赶紧解
note left : 单行文本
te -> dev
note left
多行文本
多行文本
多行文本
end note
@enduml
除使用 left 进行方位标记外,还可以使用 right 。
消息数字序号
当时序图中存在很多消息时,会产生很大的理解障碍。通过 autonumber 关键字,可以自动把消息按先后顺序加上数字序号。
@startuml
autonumber
title Bug简易流程
te -> dev : 提了个bug,赶紧解
activate dev
dev -> dev : 改bug中
dev --> te : 改完了,麻烦回归一下
deactivate dev
@enduml
分组
@startuml
autonumber
title 需求分析建议流程(不完全)
group 需求文档获取
te -> pm : 需求文档
activate pm
pm -> pm : 写需求文档
pm -> te
deactivate pm
end group
group 需求分析
te ->> dev : 详细设计文档
activate te
group 需求澄清
te -> te : 了解需求
te -> te : 需求反串讲
end group
group 需求分析
end group
group 测试设计与分析
end group
deactivate te
end group
@enduml
条件判断
条件判断为顺序图提供了强大的逻辑判断能力,极大丰富了顺序图的使用范围。在UML中使用 alt 关键字来进行条件判断。
@startuml
title 提交bug规范
te -> dev : 提交bug
dev -> dev : 查看bug信息
alt bug规范
dev -> dev : 修改bug
dev -> te : 修改完成,回归
else bug不规范
dev --> te : 无效bug,信息不完整,重新提
end
@enduml
alt 是一种特殊的group分组
循环
循环进行某一项活动,在UML中使用 loop 关键字对内部活动进行循环操作,直到条件满足后退出。
@startuml
title 提交bug
te -> te : 探索性测试
loop 直到提交完毕
te -> JIRA系统 : 提交一个bug
JIRA系统 --> te : 提交成功
end
@enduml
loop 是一种特殊的group分组
延时
在两条消息之间添加延时,可以提高顺序图的阅读性。在UML中使用 … 来添加时延。
@startuml
title 回归测试
te -> dev: 提交bug
dev -> dev : 修改bug
dev --> te : 修改完成,提交测试
... 回归测试(一天) ...
te -> dev : 回归不通过,重新改下bug
@enduml
参与组分组
@startuml
title 参与者分类
box 人类军团 #LightGreen
actor 软件测试工程师 as te
actor 开发工程师 as dev
end box
participant 用例系统 as tcms
@enduml
协作图
协作图也是互动的图表。他们像序列图一样也传递相同的信息,但他们不关心什么时候消息被传递,只关心对象的角色。在序列图中,对象的角色放在上面而消息则是连接线。
概述
通信图(Communication Diagram),也叫协作图(Collaboration Diagram),描述了对象与对象之间的协作/合作关系,侧重说明对象的消息传递,强调发送和接收消息的对象之间的组织结构。通信图的建模结果用于获取对象的职责和接口。
通信图中,对象通常是命名或匿名的类实例,也可以代表其他事物的实例。通信图描述了系统的动态情况,通过对象之间的消息传递来反映具体使用语境,使复杂的程序逻辑更容易理解。
- 自UML 2.0 之后,不再使用协作图,都统一使用通信图。
- 动态图是从静态图中抽取瞬间值的变化描述系统随时间变化的行为。动态图包括通信图、活动图、状态图等。
PlantUML并不支持通信图的语法,可以通过其他的替代方案来实现通信图的描绘,如Rose、StarUML、Visio,甚至是PPT或Word。
通信图元素
通信图由三部分组成:对象(Object),链(Link) 和消息(Message)。
对象
对象,即类的实例,是为了共同完成某个目标的群体,通信图中主要描述在完成目标过程中,对象所参与的那部分活动。通信图中的对象与顺序图中的对象一样,使用人形图案或矩形来表示,如下图,其中a表示实例名,A表示类名。
链(对象关联)
在通信图中,链由一个或多个相连的线(直线或弧线)形成,链的两端是消息发送者和消息接收者,并且消息发送者与消息接收者可以是一样的。
对象之间的箭头方向表明对象之间交换的信息流,一个对象发出消息,箭头指向对象接收消息。链用于实现消息的传输。
与类的关系不同,通信图中的链是临时关联,只在本次交互中存在,而类的关联是永久的。
消息
通信图是通过一系列的消息来描述系统的动态行为。消息可以分为四种类型:
简单消息:指示消息类型未知或不重要的消息,可默认都使用简单消息替代。
同步消息:表示前一个消息处理完成后才能处理下一个消息。
异步消息:表示处理流不需要等到消息完成或传递反馈后才继续执行。
反身消息:对象自身内部的消息处理。
通信图与顺序图差异
相同点
- 具备相似的责任主体
- 都是通过消息驱动
- 具有顺序性
不同点
- 通信图中,对象无法创建和撤销,位置没有限制。
- 协作图展示对象间的关系使得更适用于获得对象结构的理解,顺序图则更适合获取调用过程的理解。
- 顺序图强调的是时间顺序,通信图强调的是空间的顺序。
顺序图和通信图是可以相互转换的。
实例
数据库登录
数据库登录顺序图
数据库登录通信图
赤壁之战
赤壁之战顺序图
赤壁之战通信图
活动图
活动图是一个很特别的流程图。活动图和状态图之间是有关系的。状态图把焦点集中在过程中的对象身上,而活动图则集中在一个单独过程动作流程。
概述
活动图(Activity Diagram),描述了活动的顺序,展现从一个活动到另一个活动的控制流,即活动图是一种流程图。活动图描述了业务实现用例的工作流程。活动图主要由活动和动作构成,也可以支持分支、迭代、并行。
在UML中,活动图主要用于计算性和组织性过程(即工作流)建模。
实际上,在活动图引入到UML之初,是存在巨大争议的,因为活动图实际上描述的是业务流程,是一种过程化的分析方法,这让人担心面向过程的活动图对面向对象的类产生混乱。
但是,UML引入活动图是必须的,活动图的引入解决了业务目标过程化的描述。
活动最终可以细分成多个动作,动作是不可再分的步骤。
活动图元素
活动图有五部分:活动(Activity)、动作流(Action Flow)、分支(Branch)与合并(Merge)、分叉(Fork)和汇合(Join)、泳道(Swimlane)。
活动
活动表示某流程中的任务的执行,它可以表示算法过程中语句的执行。
动作流
所有动作状态之间的转换称之为动作流。
分支与合并
分支一般用于表示对象类所具有的条件行为。条件行为用分支和合并表达。
分叉与汇合
分叉可以用来描述并发线程。汇合代表两个或多个并发控制流同步发生,当所有的控制流都达到汇合点后,控制才能继续往下进行。
泳道
泳道将活动图中的活动分成了若干小组,并把每一组制定给负责这种活动的业务组织,通常为对象。泳道区分了负责活动的对象,明确地表示哪些活动是由哪些对象触发的。
每个活动只能明确地属于一个泳道,并且泳道要负责泳道内的全部活动。
泳道没有顺序,不同泳道中的活动既可以顺序进行,也可以并发进行,动作流和对象流都可以穿越分割线。
UML语法
PlantUML中有新版和旧版活动图语法,本文以新版语法为准进行说明。
活动
活动以 冒号(:)开始,以分号(;)结束,中间可以是一行或多行文本内容。
@startuml
: Hello UML Activity(单行);
-> 箭头上的文本;
: Hello UML Activity Again(多行)
1. 多行文本内容。
2. 多行文本内容;
@enduml
开始/结束
在活动图中,使用start关键字表示开始,使用end关键字表示结束。
@startuml
start
: Hello UML Activity(单行);
: Hello UML Activity Again(多行)
1. 多行文本内容。
2. 多行文本内容;
end
@enduml
条件判断
UML中使用 if/then/elseif/else 来对判断进行设置,并且判断文案放到括号中。
单条件判断
直接使用if 、then 、else 来进行单条件判断,并且在UML图中展示时,会汇合成另一个条件判定(可忽略)。
@startuml
start
if (测试用例是否评审?) then (yes)
: 入库存档;
else (no)
: 进行测试用例评审;
endif
stop
@enduml
多条件判断
@startuml
title VIP等级判断
start
if (充值金额 > 5000) then (yes)
: 高级VIP逻辑处理活动;
stop
elseif (充值金额 > 500) then (yes)
: 普通VIP逻辑处理活动;
elseif (充值金额 > 50) then (yes)
: 穷逼VIP逻辑处理活动;
else (没有任何充值)
: 屌丝逻辑处理活动;
endif
stop
@enduml
循环
UML中有repeat和while循环,其关系与do/while 和 while 是一样的,repeat会先进入循环体,执行一次结束后再做判断,而while则会先进行判断是否满足进入循环体的条件。
repeat 循环
@startuml
title 测试设计流程
start
repeat
:第n个需求澄清;
:第n个需求分析;
:第n个需求进行测试设计;
repeat while (还有需求要做测试设计吗?)
stop
@enduml
while 循环
@startuml
title 测试设计流程
start
while (有需求要做测试设计吗?)
:第n个需求澄清;
:第n个需求分析;
:第n个需求进行测试设计;
endwhile
stop
@enduml
并行处理
使用 fork/fork again 进行并发处理
@startuml
title 开展性能测试
start
if (是否需要开展性能测试?) then (yes)
fork
: 功能测试;
fork again
: 回归测试;
fork again
: 探索性测试;
fork again
: 性能摸底测试;
end fork
else (不开展性能测试)
:回归测试;
:探索性测试;
endif
stop
@enduml
泳道
通过 |泳道名称| 来设置泳道,在需要对该泳道进行表述时,可以 |泳道名称| 进行泳道的切换。
一个活动只能在一条泳道上,如果需要多个泳道同时处理,那么就需要使用并发。
@startuml
title 测试用例评审流程
|测试工程师|
start
: 测试用例评审邀请;
|#AntiqueWhite|开发工程师|
: 了解测试设计思路;
: 分析测试设计中的缺陷;
|测试工程师|
: 组织评审会议;
fork
|测试工程师|
: 概要阐述测试设计思路;
: 答疑;
fork again
|开发工程师|
: 提出会议前准备的问题;
end fork
|测试工程师|
: 根据评审意见进行用例修改;
stop
@enduml
状态图
对象拥有行为和状态。对象的状态是由对象当前的行动和条件决定的。状态图statechart diagram显示出了对象可能的状态以及由状态改变而导致的转移。
概述
状态图(State Diagram)主要用于描述对象在其生命周期内的状态变化,这个变化表现为一个对象所经历的状态序列引起状态转移的事件,以及因状态转移而伴随的动作。
状态图元素
在有限状态机的学习中,我们把状态机的要素归类为现态、条件(事件)、次态。
对于更规范的UML活动图中,其元素组成概括起来主要为 状态 和 转换。
状态
初始结束状态
初始状态用黑色实心圆圈表示,结束状态用白色圆圈内嵌套黑色圆圈表示。
@startuml
[*] -> 睡觉
睡觉 -> [*]
@enduml
普通状态
定义状态有两种方式,一种是使用state关键字定义,另一种是直接使用箭头指向 未定义的名称 ,此未定义的名称会被当做是一个状态。
@startuml
state 测试设计
state 测试执行
[*] -> 未定义状态
@enduml
状态别名
为了提高使用效率,状态图提供 别名 ,使用 state 关键字定义状态名称,并且状态名称需要用 “” 引用,否则会报语法错误。
@startuml
state "测试设计" as desg
state "测试执行" as exec
@enduml
注意,组合状态也可以使用别名。
组合状态
一个状态内部也可能有其他子状态图组成,可以通过关键字 state 和 花括号来定义 组合状态。
@startuml
state "测试设计" as desg
state "测试执行" as exec
state desg {
state "需求澄清" as cla
state "需求分析" as ana
state "测试建模" as model
state "测试分析评审" as review
[*] -> cla
cla -> ana
ana -> model
model -> review
}
[*] -> desg
desg -> exec
exec -> [*]
@enduml
并发状态
使用 — 或 || 作为分隔符来合成并发状态。
@startuml
state "回归测试" as reg
state reg {
[*] -> 探索性测试
探索性测试 -down-> [*]
--
[*] -> 回归Bug
回归Bug -down-> [*]
--
[*] -> 修复Bug
修复Bug -down-> [*]
}
[*] -> reg
@enduml
并发状态无法使用定义好的状态
转移(Transition)
转移是两个状态之间的一种关系,表示对象将在源状态中执行指定动作后,并在某个特定事件发生且在某个特定的条件下进入目标状态。
每个转移只允许有一个事件触发,一个事件只允许有一个动作。
事件方向
@startuml
[*] -right-> 向右
[*] -left-> 向左
[*] -up-> 向上
[*] -down-> 向下
@enduml
触发事件
事件有四种类型:
- 调用:源对象请求调用目标对象的操作。调用一般是同步信号,需要等待目标对象操作完成后源对象才可以接管控制。譬如当制定好测试计划后,选择自动化测试或手工测试后,就会进入 自动化测试状态 或 手工测试状态。
@startuml
state "制定测试计划中" as plan
state "手工测试中" as manual
state "自动化测试中" as auto
[*] -> plan
plan --> manual: 执行手工测试
plan -> auto: 执行自动化测试
@enduml
改变:频繁改变的表达式,只要表达式为真,事件就会发生。譬如当需求文档准备就绪后,我们就可以进入测试设计阶段,否则处于等待状态。
@startuml state "测试设计状态" as design state "等待状态" as pending [*] -> pending pending --> design : when(需求文档就绪) @enduml
信号:对象之间通过发送信号和接收信号实现通信。信号一般是异步机制,无需等待接收信号。譬如 软件测试工程师给开发工程师提了一个Bug单,此时软件工程师无需等待反馈也可继续工作,提bug就是一个信号。
- 时间:在绝对时间或某个时间间隔内发生的事情所引起的事件。譬如时间到18:00后,状态从 上班 就变成 加班或下班。
@startuml
state "上班" as work
state "下班/加班" as off
[*] -> work
work --> off : when(18:00)
@enduml
条件
当触发事件发生后,需要判断 条件 是否满足才能进一步确认是否能够达到目标状态。
@startuml
state "上班" as work
state "下班" as off
state "加班" as over
[*] -> work
work -> work : 未到18点
work --> over : 到18点 [未完成任务]
work --> off : 到18点 [完成任务] / 执行用例
@enduml
自身转移
状态是可以由返回自身状态的转移,这种称之为自身转移。
@startuml
state "睡觉" as sleep
[*] -> sleep
sleep -> sleep
@enduml
状态多行描述
@startuml
state "睡觉" as sleep
sleep: 第一行文本
sleep: 第二行文本
sleep: 第三行文本
[*] -> sleep
sleep -> sleep
@enduml
状态图步骤
- 寻找被测对象的主要状态
- 确定状态之间的转换关系
- 细化状态内的活动与转换
- 绘制状态图
组件图
组件图又称为构件图,描述在软件系统中遵从并实现一组接口的物理的、可替换的软件模块。
组件图给提供了将要建立的系统的高层次的架构视图,这将帮助开发者开始建立实现的路标,并决定关于任务分配及(或)增进需求技能。
部署图
部署图描述的是系统运行时的结构,展示了硬件的配置及其软件如何部署到网络结构中。部署图通常用来帮助理解分布式系统,一个系统模型只有一个部署图,用于可视化的软件组件部署的系统中的物理组件的拓扑结构。
概述
部署图(Deploy Diagram),也叫拓扑图(Topology Diagram),主要用于显示软件产品中硬件和软件的物理架构图。从部署图中,我们可以了解到软件和硬件之间的物理拓扑、连接关系以及处理节点的分布情况。
部署图元素
部署元素
PlantUML中定义了很多关键字用于对不同类型节点的说明。
@startuml
actor 角色
agent 代理
artifact 物件或工件
boundary 边界
card 卡片
cloud 云端
component 组件
control 控制
database 数据库
entity 实体
file 文件
folder 文件夹
frame 框
interface 接口
node 节点
package 包
queue 队列
stack 堆栈
rectangle 矩形
storage 存储
@enduml
- 节点:表示系统的计算资源(如计算机、传感器、打印设备或服务器等)的模型元素。
- 工件:表示软件系统中的物理实体的模型元素,如可执行文件、库、文档、数据库等。
元素详细描述
通过 [] 可以增加元素的详细描述,并且通过 ==== / …. / —— 来进行分割文本描述。
@startuml
node 测试设备 [
第一行描述
----
第二行描述
....
第三行描述
====
第四行描述
]
@enduml
元素嵌套
通过 {} 来对父节点的内部进行定义,使得元素之间存在父子关系(即嵌套)。
@startuml
node 父节点 {
node 子节点1
node 子节点2
}
@enduml
链接关系
部署图中元素之间的关系存在一定的关系,这些关系与 类图 中的关系相似。
@startuml
node node1
node node2
node node3
node node4
node node5
node1 ..|> node2 : 实现
node1 ..> node3 : 使用
node1 --|> node4 : 继承
node1 <--> node5 : 关联
@enduml
部署图绘制步骤
- 找出系统关联的节点(包括软件和硬件)
- 逐个确定每个节点与其他阶段的关联关系
- 根据关联关系,连接两个节点
- 重复步骤2和3,直到所有节点都完成
部署图之间的难点在于如何找出系统的节点,建议:
- 找开发工程师了解被测对象的内部结构及上下游关系。
- 找资深测试工程师了解被测对象的整体架构图,涉及到的软硬件。
实例说明
CI概要部署图
@startuml
title CI概要部署图
actor 测试工程师 as auto
database 自动化测试数据库 as db
node 办公电脑 as pc
node CI主服务器 as ci_master
node CI从服务器 as ci_slave
node 日志服务器 as log_server
node 报告服务器 as report_server
cloud 办公网络 as public_cloud
cloud 自动化私有网络 as auto_cloud
node 测试设备 as dut
auto ..> pc
pc -> public_cloud : HTTP
public_cloud -> pc
public_cloud <--> auto_cloud : 跳板机
public_cloud -> log_server : FTP/SMB
log_server -> public_cloud
public_cloud -> report_server
report_server --> public_cloud
report_server --> db : tcp
ci_master -> auto_cloud
auto_cloud -> ci_master
ci_master -> db : tcp
db -> ci_master
ci_master --> ci_slave : ssh
ci_slave -> ci_master
ci_slave --> dut : usb
dut -> ci_slave
@enduml
简易部署流水线
@startuml
queue 部署流水线 {
node 代码服务器 as code
node 编译服务器 as comp
node 工件服务器 as air
node 测试执行机 as exec
node 报告服务器 as report
node 部署机器 as deploy
code -> comp
comp -> air
air -> exec
exec -> report
report -> deploy
}
@enduml