
小C同学说,通过几期Cucumber的基本知识学习,他迫不及待地编写了自己的cucumber。可是他的features显得即简单又笨拙!怎么才能写出漂亮的features呢?别急,今天我们就来讲讲如何优化features。
Q&A 1:数据表
小C同学问:我的scenario有很多组数据,所以我用多个And来存放数据,功能实现了,但是可读性很差,很多steps乍一眼看都是一样的,特征不明显,怎么办?
Given a User “July Shi" born on August 29, 1988
And a User “Jenny Jing" born on January 8, 1985
And a User “Sasha Ma" born on October 9, 1990
七姑娘答:Bu Ling Bu Ling, 数据表该闪亮登场啦。
数据表(date table)是一种扩展Gherkin的方法,将Scenario中的多组数据用数据表存储,一目了然,清晰可见。闲话不多说,将你的例子用数据表包装一下:
Given these Users:
| name | date of birth |
| July Shi | August 29, 1988 |
| Jenny Jing | January 8, 1985 |
| Sasha Ma | October 9, 1990 |
注意:数据表用管道符“|”分割单元格,cucumber会忽略掉单元格中的空格。
Q&A 2:Subfolder & Tag
小C同学问:当我只有极少的features时,很好管理。可随着features逐渐增多,查找特定的feature就变得很繁琐,如何有效的组织我的features结构呢?
七姑娘答:我们通常采用两种方法来管理features:(1). 利用Subfolder来分类; (2). 用Tag来为Scenario添加标签。
Subfolder: 可以将features按照功能、优先级、或者user类型等有效的方式进行分类,并在features下新建对应的文件夹对其进行管理。例如我们将WeChat的测试features按照功能划分:
features/
Login/
Login.feature
AccountValidation.feature
Chat/
TextMessage.feature
VoiceMessage.feature
Picture.feature
VideoCall.feature
RedPacket.feature
AddContacts/
Search.feature
ScanQRCode.feature
MobileContacts.feature
OfficialAccounts.feature
那么,我们如何来执行这些子文件夹中的features呢?
(1). 如果你想执行全部的features,直接采用$ cucumber命令来执行。Cucumber会执行features目录下的所有Scenarios。
(2). 如果你想执行特定子目录下的features,我们可以为其指定路径。
例如:$ cucumber features/Login/AccountValidation.feature
不过,这时候会存在一个问题,cucumber不知道去哪里匹配对应的step definitions,从而将其标记为undefined。但实际step definitions是存在的。因此我们需要明确告诉Cucumber去哪里匹配step definitions。这里是从根目录features下查找,因此将命令修改成: $ cucumber features/Login/AccountValidation.feature -r features
Tag: 我们也可以用Tag为Scenario添加标签(一个Tag包含:’@’符号+标签名)。例如,用story No.来标记:
@#145
Scenario: Add two numbers
Given the input "2+2"
When the calculator is run
Then the output should be "4”
也可以添加多个标签,用空格分开:
@#145 @Addding
Scenario: Add two numbers
Given the input "2+2"
When the calculator is run
Then the output should be "4"
用Tag标记有三个意图:
(1). 文件:标签作为一种文件形式存在,起到说明作用,比如用Story No.来标记可以使人清楚地看到该Scenario隶属于某个story。
(2). 过滤:Cucumber允许用Tag作为过滤器,选择特定的Scenario。
(3). hook(锚):锚定一段ruby代码块来执行,被tag hook的代码总是在Scenario开始或结束时执行。
执行用Tag标记的Scenario:
$ cucumber -- tags @TAGNAME
Q&A 3:Hooks
小C同学问:你刚提到hooks,那是个什么东东?
七姑娘答:Hooks,锚是什么?锚是一种停船用具,一端连接到船上,另一端像个钩子,沉入水底,将船体固定住。
Cucumber Hooks: Cucumber也支持hooks,即用“before”或“after”来标记一段代码块,这段代码块可以存放在support、step definition等任何位置,用before锚定的代码总是在Scenario之前执行,同理,用after锚定的代码总是在Scenario执行之后执行。
例如,我们在support目录下添加一个hooks.rb文件。并存放如下代码:

执行看看,发现和预期一样,在Scenario执行之前打印出用Before标记的内容,执行结束之后打印出After标记的内容。

在实际编码中,通常用before和after hooks来标记setup和teardown方法。
Q&A 4:Tagged Hooks
小C同学问:明白了,Hooks的作用就像Java中的注解一样,可是Tagged Hooks又是个什么西西?
七姑娘答:Tagged Hooks, 是一种特殊的Hooks。
Tagged Hooks: 有时候,我们不需要对全部的Scenarios执行某些方法,只需要针对某些特定的Scenarios执行某些方法,这时,就要用到Tagged Hooks.
例如上面的例子,假如我们只需要在运行@Adding标记的Scenario之前打印’Start Adding’, 之后打印’Stop Adding’,就可以使用Tagged hooks:

运行下看看:

Q&A 5:Examine the Scenario
小C同学问:Java的有些注解可以添加参数。Cucumber Hooks可以携带参数吗?
七姑娘答:当然可以。我们可以通过为hooks添加参数来验证Scenario。
Examine the Scenario: 我们可以通过为hooks添加参数来验证Scenario。比如,我们需要在执行Scenario执行之前打印Scenario的名称,在执行结束之后,如果验证失败,则打印“Oh my god”;如果成功,则打印“Ahahaha good ~~~~”

运行下看看:

Q&A 6:Around Hooks
小C同学问:如果我想让某些Scenario多次执行,如何实现呢?
七姑娘答:很简单,使用Around Hooks。
Around Hooks: 与before和after hooks不同的是,around的权限更大,它具备两个参数,可以用来控制Scenario执行的次数。比如我们要让Scenario执行两次。可以这样操作:

运行下看看:

更多Cucumber知识,请查看: