Cucumber 之 Step Definitions"/>
Cucumber 之 Step Definitions
最近一直处于厌食、失眠、出虚汗的状态,体力明显不支。下午跟小伙伴做完例行的健身操,头晕眼花、恶心耳鸣。仔细想想,饮食、休息、健身和工作学习本该是个良性循环,必须环环相扣。一环欠了债,整个系统都有可能崩塌。所以“身体是革命的本钱”,这句话一点儿不假。工作学习固然重要,但和吃饭睡觉一样,是个长期的过程,不能一蹴而就,也不能三天打鱼两天晒网。
我们已经学习了Cucumber的Gherkin语法。“.feature”文件就是用Gherkin语法结合自然语言编写的Scenario和Step,用来告诉Cucumber“要做什么”。那么,具体“怎么做”又是如何实现的呢?
先来回顾一下创建一个Cucumber Test的三步走战略:
Step 1. 创建features folder;
Step 2. 编写.feature文件;
Step 3. 编写step definitions.
没错,“怎么做” 就是由Step Definition来实现。
Step Definitions:
Step Definition相当于业务领域和程序领域之间桥梁,用ruby语言编写。它都有什么作用呢?可以从两个方面来理解:
a. 解释:将“.feature”文件中的Scenario和Step解释成可执行的ruby代码;
b. 决定做什么:告诉系统按照ruby自动化代码块来执行。
Step vs Step Definition:
我们必须搞清楚两个概念:Step和Step Definition
(1). Step
“.feature”文件包含多个Scenario,Scenario又包含多个Step(由Gherkin关键字引导,自然语言编写)。就step本身而言,它只是一种文件,需要Step Definition赋予它生命。
(2). Step Definition
Step Definition是一段ruby代码,存放在features/step_definitions文件目录里。它仿佛在告诉Cucumber:“如果你看到一些长得像***的step,就是我要让你做***”。因此Cucumber需要将Step Definition与“.feature”文件中的Step进行match。
用一个例子来解释这个match。
Feature: Cash withdrawalScenario: Successful withdrawal from an account in creditGiven I have $100 in my account When I request $20Then $20 should be dispensed
Cucumber执行feature时,从Scenario的第一步“Given I have $100 in my Account ”开始扫描,同时查找是否存在任何Step Definition来匹配这段自然语言。
下面是与之匹配的Step Definition:
Given /I have \$100 in my Account/ do
# TODO: code that puts $100 into User's Account goes here
end
Step Definition就是用正则表达式来做match。这段代码就是在告诉Cucumber:“如果你看到一些长得像‘/I have \$100 in my Account/’的step,就是我要让你做‘TODO"’部分的内容”。
在ruby里,正则表达式由“/”符号开始,由“/”符号结束。这里的dollar符用“/”标记,以此来使dollar符保持其字面意思。因为在ruby里,dollar符具有特殊意义。
Step Definition 之 方法(Methods):
Step Definition是一段ruby代码,因此它必须包含方法,变量,参数,返回值等等。
那么它的方法是什么呢?
我们在Step Definition里看到的Given、When和Then就是Cucumber方法。
在上述例子中,调用Cucumber的Given方法,告诉Cucumber要注册一个Step Definition。通过Given方法传递两个概念:
(1).用以匹配“.feature”文件中step的正则表达式“/I have \$100 in my Account/”和一段ruby程序块。
(2).Cucumber保存这段ruby程序块,直到找到与之匹配的step后来执行这段程序。
实际上,在Step Definition与Step进行匹配时,Cucumber并不关心是Given、When还是Then方法。因为在底层,所有的keywords只有同一个别名:Cucumber:: RbDsl#register_rb_step_definition。那这些keyword在Step Definition里究竟有什么意义呢?其实真的没什么意义,只为了帮助我们理解程序。而step与step definition的match只看正则表达式。
Step Definition 之 参数(Arguments):
说完了方法,再来说说参数。
细心地人就会发现,正则表达式“/I have \$100 in my Account/”表示“我有100 dollar”,但如果我还有其它金额呢?难道需要重新写一个step definition吗?当然不是。这时候,step definition的参数(arguments)就需要出场了,Cucumber可以将具体值以参数的形式传递给程序块。
我们可以用通配符”.*”来代替正则表达式中的具体数值,并增加参数(Arguments)。Step Definition通过正则表达式匹配到Step以后,将从step中获取的具体数值传递给Step Definition中的参数。
Given /I have \$(.*) in my Account/ do |amount|
# TODO: code that puts $100 into User's Account goes here
end
当然,也可以限定参数的范围,比如数字。
Given /I have \$([0-9]*) in my Account/ do |amount|
# TODO: code that puts $100 into User's Account goes here
end
比如小写字母:
Given /I have \$([a-z]*) in my Account/ do |amount|
# TODO: code that puts $100 into User's Account goes here
end
当然,还有很多简写字符,比如:
\d 代表数字[0-9].
\w 代表字母、数字、下划线[A-Za-z0-9_].
\s 代表空格,Tab或者回车[ \t\r\n].
和大多数程序语言一样,Cucumber也支持多个参数。
Step Definition 之 返回结果:
前面讲到,“.feature”文件告诉Cucumber要做什么,Step Definition告诉Cucumber怎么来做。那它如何来通知Cucumber是成功了还是失败了呢?
和大多数测试工具一样,Cucumber也通过抛异常(Exception)来传递失败。Cucumber执行Scenario时,一次执行一个Step,如果这个Step执行通过,它就继续移去执行下一个Step;如果失败,就抛出一个异常。下图展示了Cucumebr如何来执行Scenario。
与其他测试工具不同的是,Cucumber的返回结果略为复杂。包含四种状态:
Undefined
Pending
Failed
Passed
Undefined:
正如上面的流程图所示,当Cucumber找不到与Step Definition对应的Step时,将Step标记为Undefined状态,并结束Scenario的执行。其余的Step要么被标记为Skipped,要么同时被标记为Undefined状态。
Undefined状态通常为黄色标记。
Skipped用蓝色标记。
Pending:
当Step Definition发现Step Definition未完成时,就会将Step标记为Pending状态,并结束Scenario的执行。同样,其余的Step要么被标记为Skipped,要么被标记为Undefined状态。
Cucumber怎么知道Step Definition未完成呢?这需要Step Definition亲自告诉它。
像这样,当你的ruby程序块未完成时,可以手动将其标记Pending。这样Cucumber就会知道Step执行失败了,但是是因为一种特殊的原因。
Pending 状态通常也为黄色标记。
为什么也要用黄色呢?我个人认为,Undefined表示未找到Step Definition,Pending状态表示Step Definition找到了,但未完成,从某种意义上来讲,这两种状态的性质是一样的。
Failed:
当Step Definition执行失败时,就抛出一个失败的异常,将step标记为Failed,并结束Scenario的执行。同样,其余的Step被标记为Skipped。
Failed状态用红色标记。
Passed:
当step执行通过时,Cummber将该step标记为Passed,转而执行下一个Step。
Passed状态用绿色标记。
更多Cucumber知识,请回顾:
初识Cucumber
第一个Cucumber Test
Cucumber语法之Gherkin
更多推荐
Cucumber 之 Step Definitions
发布评论