写点什么

增强 UML 符号的提案

2013 年 7 月 03 日

需求与测试用例,特别是验收测试,是密切相关的。敏捷方法本身基于测试驱动方法,尤其强调这一点。可以增强 UML 用例的符号以使增强后的 UML 工具可以正确地处理用例与测试之间连接。

验收测试是设计的一部分

"测试驱动开发"或 Dan North 观点里的"行为驱动开发"是敏捷范式里最好的实践之一。当我第一次读到 BDD 的介绍时,对文字模板的"可执行规格"概念的印象特别深刻:

(T1) Given <context> {and <context>}, when <event>, then <outcome> {and <outcome>}

“可执行规格”,多好的想法!不管在所有环境中这一概念的可用性情况,比如很难想象如何按字面意义将它应用到一个合同文档中,但是它作为隐含信息却改变了我看待测试的方式:

  • 验收测试是设计的一部分!

为什么仅仅是验收测试?单元测试、集成测试、系统测试又怎样呢?

  • 单元测试通常用于检测低层构件,如类方法,它们受很多实现决策的限制,以至于需要认真地考虑:我没见过将单元测试作为设计组件,但可作为辅助从源代码中用工具自动生成。
  • 系统(或子系统)测试用于检测高层组件交付时的准备状态,所以我将系统测试看作验收测试。
  • 集成测试提出了问题:我的简单回答是它应该被看作验收测试。或者"应该"这个词需要更深的认识,它牵涉到"黑盒测试"和"白盒测试"。"黑盒测试"聚焦于系统做什么,"白盒测试"则聚焦于系统如何做。"白盒测试"类别中多一个测试失败,则离"验收"的类别更远。换句话说"黑盒测试"类别中多一个集成测试失败,离"验收"类别就更近了。

一些敏捷方法,包括 XP(eXtreme Programming)和 Scrum 在内,建议将用户故事作为需求的产出。一些作者,例如 Mike Cohn Scott Ambler ,认为用户故事如果简洁,则特别高效。并且,笼统地提议采用以下模板 5:

(T2) As a <role>, I want to <goal/desire>, so that <benefit>

第一印象是"so that"子句是可选的 6,但 Chris Matts7 觉得它是提出以下模板的基础:

(T3) In order to <receive benefit> as a <role>, I want to <goal/desire>

我的观点是接受 Chris 的论点且认为"in order to"子句或相同的"so that"是关键。事实上,我认为任何需求都需要至少一个验收测试和这样一些子句,它们应该用于沟通验收测试的期望: <goal/desire> 表明测试的产出应该符合

在一个同时管理用户故事和验收测试的假想的工具中,每个验收测试应该链接到一个特定用户故事的"so that"子句,而不是直接链接到用户故事。

正好说到点子上,我的用户故事模板的愿景是:

(T4) As a <role>, I want to <goal/desire>, so that <benefit> {and <benefit>}

每个"benefit",而非完整的"so that"子句,都应该有至少一个相关的验收测试。

UML 用例与验收测试

我想知道同样的概念是否可以通过 UML 用例图表达。在这篇文章中"用例"应该总是解释为"UML 用例图"或"UML 用例工件",我避免使用用例描述的原因是它们与 UML 相比既有期望的特性也有不期望的特性。我的目标是呈现一个十分合适 UML 图的想法。

图 1 中高亮显示的是一个用户故事的一个部分与用例图之的双向连接:"As a “子句对应"UML 角色”,"I want to <goal/desire>“子句对应"UML 用例”。它可看成是结构关系,具有理论上的可能性,而不是一个好的或推荐的实践:有一堆例子可以嘲 mockery 弄这翻译,参见 Alistair Cockburn8 尖锐的讨论。

图 1 : 用户故事与 UML 用例间的关联

UML 用例产出并不能严谨地表达"so that"子句,而只能用注释的方式介绍它(如图而):

图 2 : 用户故事与 UML 用例间的关联

在这里,UML 用例比用户故事的表现力更差:同时管理 UML 用例和验收测试的假想工具被强迫连接一个验收测试和一个用例,就像连接一个主元素(验收测试)和一个辅助元素(评论)一样在逻辑上是错误的,并且应该受到禁止。

如果 UML 用例工件允许将验收测试定义成其工件的一部分,那么情况就很不同了。我认为验收测试之于用例相当于方法之于类(如图 3)。

图 3 : 验收测试之于 UML 用例相当于方法之于类

明显,我滥用了 UML 符号来解析我的愿景。

简单和复杂需求

需求可以被划分成两类:简单需求和复杂需求。一个简单的需求只包括单一的业务功能,但一个复杂的需求则包括多个业务功能。单一功能不一定只关联到单一的 UML 用例,而通过内含(included)用例和扩展(extended)用例修饰的主用例不一定要当作复杂需求。下面通过一个例子来澄清二者的区别。

假设你有以下的干系人的请求:

(SR-1) 系统要通过添加、更新、获取条目来管理产品列表。

可以通过图 4 中的 UML 用例图来描绘,具体含有 5 个简单需求:

图 4 : 产品管理用例

你可以注意到,内含的"select product"用例并未算作简单需求。

假设你现在有以下干系人的请求:

(SR-2) 所有操作应该被日志记录以用于审核目的。

下面的天真的方法(如图 5)不能满足需求,那么实际上我们该如何定义验收测试呢?

图 5 : 对于复杂需求的天真方法

这一问题显示了强烈希望 UML 用例与验收测试耦合的原因之一:需求的最重要属性是可测试性,所以它对 UML 用例也是一样。

UML 符号允许定义抽象用例和指定的其它的用例,这使得你可画出如图 6 所示的别样的图。

图 6 : 抽象用例

这个图对于所有面向对象的专家异常清晰,而且容易向周围人解释。这里强调的是,"logged operation"用例的抽象本质决定其指派指定的具体用例来提供所需的验收测试。

留意我之前称作“简单需求”和“复杂需求”之间巨大差异:前者允许与测试间的直接链接,后者没有这种工具并且要依赖于其它特性。

问题是如何保证定义出所有的(验收)测试。

测试作为 UML 用例方法

下面我在图 7 中修改了图 6(这里再一次滥用了 UML 符号)。

图 7 : 测试作为用例方法

此前介绍的假想工具可以自动处理抽象"test logged operation",例如为所有具体派生用例生成需要的测试。注意,用例应能概括测试用例,但细化测试用例却不是它的责任:"use case test method"应该包括名称,可能包括输入参数,和模式(例如,inspection、demonstration、log analysis 等等)。

结论

我认为用户故事是收集干系人请求是一个很有价值的工具,但是它们要求更加详细的阐述以细化需求。此外,它们不完全适合于融入图形工具:因此它们将或多或少地相当于简单 UML 用例。UML 用例提供丰富的功能,而且尽管它们已经陈旧,它们仍然存在隐含的可能性:具有增强的空间。很多现代设计工具将其它图形添加到 UML 图形中以便支持需求、测试案例以及元素之间的某种可追溯性。我想更好的解决方案是使 UML 用例符号更强大,就如前面段落所描绘的一样:我仅看到将(验收)测试封装到 UML 用例中的优点,这也可能打开了介绍新 UML 分类符的门,包扩测试细节的"验收测试"。我将以重申我的观点来结束本文,我卑微的观点是,验收测试是设计的一部分,如同敏捷实践或含蓄或明确地声称的那样。在更完整的框架中,系统的定义——高质量的定义 - 符合以下等式"系统定义"="需求"+"架构"+"验收测试",但完整地解释这一等式就需要在写一篇文章了。

引用

  1. 关于行为驱动开发看这里这里
  2. 黑盒测试
  3. 白盒测试
  4. “黑盒“测试是一个功能测试的同义词,而“白盒”测试是指结构化测试:参见这个 例子
  5. 它由 Connextra 的一个团队于 2001 年开发。
  6. Mike Cohn 可能是首位建议该观点的人。
  7. 想了解这个作者,请阅读这篇文章
  8. Alistair Cockburn 的讨论。

关于作者

Raul Rugiero是凯捷的一个企业软件工程师,在信息系统的生产和交付上有 20 多年经验。他曾在多个行业工作过,如公共行政管理、电信和近年来的航空与国防。Raul 曾担任和持续担任各种角色,他最喜爱的角色是软件架构师,现在他主要处理需求分析、架构设计、项目技术领导和任何合适的工作,甚至组件开发。他不是任何特定技术或方法论的粉丝,但他根据自己兴趣跟随各种技术及方法论的演化。

查看英文原文: A Proposal to Enhance the UML Notation


感谢马国耀对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2013 年 7 月 03 日 08:101619

评论

发布
暂无评论
发现更多内容

Homework - 数据结构与算法

River Tree

极客大学架构师训练营

第八周总结

Acker飏

第八周总结

LEAF

当DataNode 节点宕机的时,HDFS处理过程时序图

stars

第8周数据结构与算法&网络与数据库

架构师训练营 - 第八周 - 总结

桔子

架构师训练营第 0 期 - 第 8 周 - 学习总结

第8周回顾

慵秋

JVM详解之:HotSpot VM中的Intrinsic methods

程序那些事

Java JVM GC

视频丨包不同的沙雕敏捷之砸锅卖铁买兰博

华为云开发者社区

程序员 运维 敏捷 敏捷开发 技术人

要都练基本功

架构师

wordpress迁移+更换域名

wood

WordPress

面试官问:僵尸进程和孤儿进程有了解过吗

Java小咖秀

Linux 学习 面试 进程 经验

判断两个链表是否合并

Acker飏

学习总结 - 架构师训练营 - 第八周

走过路过飞过

架构师训练营week08 学习总结

GunShotPanda

Developer 转型记:一个开发平台的“魔力”

华为云开发者社区

华为 AI 开发者 开发者工具 华为云

第九周作业

新世界

单向链表合并算法

走过路过飞过

架构师训练营第8周学习总结

TH

架构师训练营week08 作业

GunShotPanda

使用Spring Validation优雅地校验参数

Java课代表

springboot

该学一学了!零基础入门Docker

程序员的时光

Docker

一图看懂华为云DevCloud如何应对敏捷开发的测试挑战

华为云开发者社区

微服务 敏捷开发 测试 云服务 华为云

架构师训练营 - 第八周 - 作业

桔子

架构师训练营 第 8 周总结

Jam

架构师训练营 - 总结 8

进击的炮灰

架构师培训 -08总结 数据结构算法,网络通信协议,非阻塞网络 I/O,数据库原理

刘敏

【解构系统设计面试】什么是系统设计?以及如何设计一个新鲜事系统?

罗远航

系统设计

BFC "苦"前端久矣!

大导演

CSS 前端进阶训练营

揭秘淘宝平台广告策略,拆解最佳投放实践

华为云开发者社区

数据分析 广告 用户增长 淘宝 电商

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

增强UML符号的提案-InfoQ