UseCase事件流描述规范

文/fasiondog

整理需求用例的编写规范,分享部分UseCase事件流描述规范。其中,准则5~10、12来自《编写有效用例》([美] Alistair Cockburn 著)一书,其它为自身实践和要求。

事件流包含正常事件流、可选事件流、异常事件流程,前述三者合在一起的本质就是用文字描述的流程。事件流由文字描述的步骤组成,写作过程中应遵循以下准则,这些准则是对用例写作过程中的常见问题和最佳实践的总结。下述规范中如没有特殊说明,事件流同时指正常事件流、可选事件流、异常事件流。

准则1:文字描述与流程图保持一致

事件流的本质其实就是文本描述的流程。因此,对用例辅以说明的流程图应与文字表述的事件流保持一致。事实上,用例是以文字描述为主,流程图为辅。编写用例应该养成“先写文字后画图”的习惯。保持一致意味着:

  • 流程图中的动作(含判断)的数量与事件流中的步骤数量一致(由于不同的图形表示方法的限制,最低程度应保证和正常事件流中的步骤数量一致)
  • 流程图中的动作(含判断)与事件流中的步骤描述一致

准则2:步骤描述遵循“主+谓+宾”结构

句子的结构应简单明了:“主语+谓语动词+直接宾语”,辅以必要的修饰词。

准则3:一个步骤描述中仅包含一个主语

在一个步骤中仅包含一个主语,这意味着一个步骤描述中可以是一个执行者执行一个动作,也可以是一个执行者执行多个连贯的动作,但不能出现多个执行者执行多个不同的任务。例如:

错误的描述形式:
1.【用户】输入订购号码,【系统】发现这个号码与本月中奖号码匹配,将用户和订购号码注册为当月的中奖者,发电子邮件给销售经理,祝贺客户,并告诉他们如何领取奖金

正确的描述形式1:
1.【用户】输入订购号码。
2.【系统】发现这个号码与本月中奖号码匹配,将用户和订购号码注册为当月的中奖者,发电子邮件给销售经理,祝贺客户,并告诉他们如何领取奖金。

正确的描述形式2:
1.【用户】输入订购号码。
2.【系统】发现这个号码与本月的中奖号码匹配。
3.【系统】将用户和订购号码注册为当月的中奖者。
4.【系统】发电子邮件给销售经理。
5.【系统】祝贺客户,并告诉他们如何领取奖金。

在编写用例时,可以根据此准则,对较冗长的多个步骤进行合理的合并。所谓合理,是指合并后的步骤,应不影响可选事件流、异常事件流的插入点。

准则4:在步骤中明确标识参与人

通过在步骤中使用“【参与人】”的方式明确标识“参与人(Actor)”,防止因遗漏主语(以及部分宾语),而使读者不知道谁是活动的执行者。示例:

“【用户】插入ATM卡并输入PIN。”

准则5:从系统外部的角度来编写用例

缺少经验的用例编写者(尤其是对系统内部实现有所了解的开发人员)在描述用例场景时,经常有意或无意实现系统内部结构并试图从系统内部动作来描述系统。他们可能写出这样的句子“读取ATM卡和PIN号码,并从账户余额中扣除一定数量。”

而从系统外部来编写用例,则是:

1.【用户】插入ATM卡并输入PIN号码;
2.【系统】从账户余额中扣除一定数量。

准则6:显示过程向前推移

选择过小的步骤将导致用例过长。如果一个用例有13~17个步骤,说明每一个步骤完成的工作过少。如果将一些小的步骤合并,可以使用例的可读性更好、更清晰,并且保持原有的基本信息。一般,一个用例的步骤数量应控制在7个以内。

为了有效合并用例步骤,应找到具有较高层次目标的步骤。可以提出这样的问题“为什么参与人需要做这件事?”。可能,需要多次询问此问题才能得到满意的答案,而这个问题的答案就是步骤实现的目标。以下是一个通过问“为什么”来提高目标层次的例子。

“用户按下Tab键”

为什么用户要按下Tab键?是为了将焦点移到地址框中。为什么她要将焦点移到地址框中呢?因为在系统开始工作前,她要输入用户名和地址。她想让系统完成一些工作,为了使系统工作,她必须输入她的用户名和地址。

因此,一个清晰描述过程向前移动的主动语态句子是:

“【用户】输入名字和地址”

准则7:显示参与人的意图而不是动作

通过操纵用户界面来描述用户的动作,这是编写用例时常见的一种严重错误,它使得编写的目标处于一个很低的层次。界面细节描述使得需求文档质量变差,主要体现在:

  • 文档冗长拖沓使阅读困难、维护费用高昂。
  • 任何用户界面的变化都将导致用例文档失效

通常情况下,当一些连续步骤的数据在同一方向上运动时,可以将这些步骤合并成一个步骤(视情况而定,合理合并)。如下面的示例及对它的修改:

修改前:
1.【系统】要求用户输入姓名
2.【用户】输入姓名
3.【系统】要求用户输入地址
4.【用户】输入地址
5.【用户】点击“确定”
6.【系统】显示用户的简介

修改后:
1.【用户】输入姓名与地址
2.【系统】显示用户的简介

准则8:“确认”而不是“检查是否”

大家经常会遇到描述系统检查某个条件的步骤。而在步骤描述中,使用“检查”这个动词并不好,这样说并没有让过程明显的向前发展,它并不是真正的目的,同时它使得检查的结果是不确定的。那么为什么系统要检查条件?答案是为了确认、验证或确保某些事情。这些都是很好的可以表示目标的动词。例如,可以将“系统检查密码是否正确”替换为:

“【系统】验证密码正确”

准则9:习惯用语:“用户让系统A与系统B交互”

在编写用例时,可能会遇到如下情况,正在设计的系统A需要从系统B中获取信息,或者与系统B有一个交互过程。通常可以使用两个步骤来描述:

1.【用户】通知【系统A】从【系统B】获取数据
2.【系统A】从【系统B】获取后台数据。

上述写法虽然可以接受,但在某些情况下显得笨拙和冗余,尤其是用例比较复杂时。更好的写法如下:

1.【用户】命令【系统A】从【系统B】获取后台数据

准则10:习惯用语:“循环执行步骤X到Y,直到条件满足”

有时候,我们会遇到需要重复的步骤。对于只有一个步骤需要重复,可以直接在步骤中描述,如:“【用户】在各种各样的产品目录中寻找、直到发现所需要的产品。”

对于多个步骤需要重复的情况,可以把表达重复执行的语句放在这些重复步骤的前面或后面。例如:

1.【客户】提供账号或名字和地址
2.【系统】查出客户的爱好信息
3.【客户】选择一个商品,并做上购买的标记
4.【系统】将该商品加入客户的“购物车”中
  客户重复步骤3、4,直到客户指明自己完成了选购
5.【客户】购买所有在“购物车”中的商品

另一种形式:
1.【客户】提供账号或名字和地址
2.【系统】查出客户的爱好信息
  步骤3、4可重复执行
3.【客户】选择一个商品,并做上购买的标记
4.【系统】将该商品加入客户的“购物车”中
5.【客户】购买所有在“购物车”中的商品

注意:在表达重复语句前面不需要加上序号。

准则11:命名可选与异常事件流分支

为可选事件流、异常事件流中的分支进行适当的命名,有助于测试和理解。通过简单的命名,有利于检视分支的覆盖情况,保证所有的分支情况都得到了处理。例如某系统登录时的异常事件流:

5a.(录入密码方式认证失败)如果密码方式认证失败,返回步骤3
5b.(连续输入密码错误限制)如果连续3次输出密码错误,则锁定登录,用例结束。
5c.(录入指纹方式认证失败)如果指纹认证方式失败,返回步骤3a

准则12:条件处理的缩排方式

缩进那些指明条件如何处理的执行步骤,并在字母后重新从编号1开始,执行步骤遵循前面的准则。示例:

5a.如果输入密码错误:
  5a1.(密码错误)如果密码错误,系统提示错误信息,返回步骤4。
  5a2.(连续密码错误限制)如果连续3次输入密码错误,账户锁死,用例结束。
  5a3.(累计密码错误限制)如果当日密码错误达到10次,账户锁死,用例结束。

准则13:同一条件处理的分支应在一起

提出此准则的原因是在某些条件处理的分支中,被分别放置在可选事件流和异常事件流中,影响阅读和理解,也不利于检视发现错误。

错误的示例如下:
正常事件流:
……
3.柜面通过核心系统检验账户支取方式为预留密码;
……
可选事件流:
3a.柜面通过核心系统检验账户支取方式为印鉴——
  3a1.柜面提示“请核对印鉴”
  3a2.柜员核对印鉴后,点击任意键提交,返回6

修改后,将其统一放在可选事件流中:
可选事件流:
3a.(印鉴方式支取)如果账户支取方式为印鉴:
  3a1.【系统】提示客户核对印鉴;
  3a2.【柜员】核对印鉴后,提交系统确认,执行步骤6。
3b.(无印密或凭有效证件支取)如果账户支取方式为无印密或凭有效证件支取,【系统】提示“无印密账户不支持理财账户开户”,用例结束。
时间: 2024-12-24 03:09:50

UseCase事件流描述规范的相关文章

理解JavaScript中的事件流

原文地址:http://my.oschina.net/sevenhdu/blog/332014 目录[-] 事件冒泡 事件捕获 DOM事件流 当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆.两家公司的开发团队在看待浏览器事件方面还是一致的.如果你单击了某个按钮,那么同时你也单击了按钮的容器元素,甚至整个

javascript事件流

摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原文: 当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆.两家公司的开发团队在看待浏览器事件方面还是一致的.如果你单击

深入理解javascript事件流

摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原文: 当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆.两家公司的开发团队在看待浏览器事件方面还是一致的.如果你单击

关于事件流,事件冒泡和事件捕获

1.事件流 假设有这样一个场景: 有一个导航条:div > ul > li > a,每个元素块宽高一样,就像是一组同心圆.如果我们点击a元素,那么浏览器会认为单击事件不仅仅发生在a上.换句话说,在我们单击a元素的同事,我们也单击了容器中的其他元素. 事件流描述的是从页面中接收事件的顺序.但有意思的是,IE 和 Netscape 却分别提出了不一样的事件流概念.IE 的事件流是事件冒泡,而Netscape的事件流是事件捕获流. 那么问题来了,什么是事件冒泡?什么是事件捕获? 2.事件冒泡

深入了解javascript事件流

摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原文: 当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆.两家公司的开发团队在看待浏览器事件方面还是一致的.如果你单击

javaScript事件流是什么?

一.事件 事件是文档或者浏览器窗口中发生的,特定的交互瞬间. 事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字. 事件是javaScript和DOM之间交互的桥梁. 你若触发,我便执行--事件发生,调用它的处理函数执行相应的JavaScript代码给出响应. 典型的例子有:页面加载完毕触发load事件:用户单击元素,触发click事件. 二.事件流 事件流描述的是从页面中接收事件的顺序. 1.事件流感性认识 问题:单击页面元素,什么样的元素能感应到这

JavaScript——事件流(事件冒泡和事件捕获)

1.事件流 当浏览器发展到第4代时,浏览器开发团队遇到了一个问题:页面中的哪个元素会拥有某个特定的事件?当你单击某个按钮时,显然该单击事件并不仅仅发生在按钮上,它还发生在按钮的所有祖先元素上,比如按钮的容器元素,容器元素的父元素,甚至整个页面document.但是,哪个元素最先接收到该事件呢?页面接收事件的顺序又是怎样的呢?由此引出了事件流的概念.事件流描述的就是从页面中接收事件的顺序. 2.两个模型 Netscape和Microsoft给出了两个不同的结论.Netscape说document会

事件流

1.JavaScript与HTML之间的交互时通过事件实现的,事件流描述的是对象接收事件的顺序 2.事件流有两种,事件冒泡和事件捕获 3.事件冒泡:事件首先发生在最具体的对象上,然后沿着DOM树向上传播(不会受css影响),每一级都会发生事件,直到window对象,所有现代浏览器都支持事件冒泡 阻止冒泡:将当前事件函数中event对象的cancelBubble属性设置为true即可,这个方式只能阻止当前事件的冒泡 5.事件捕获:window首先接收到事件,沿着节点树传播,最具体的节点最后接收事件

JavaScript中的两种事件流

JavaScript中的两种事件流 事件流描述的是从页面中接收事件的顺序.提出事件流概念的正是IE和Netscape,但是前者提出的是我们常用的事件冒泡流,而后者提出的是事件捕获流. 第一部分:事件冒泡 即事件开始由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档). 下面举一个简单的例子: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"&