Cucumber(2)——目录结构以及基本语法
目录
回顾
在上一节中,我大致的介绍了一下cucumber的特点,以及基于ruby和JavaScript下关于cucumber环境的配置,如果你还没有进行相关的了解或者环境的配置,你可以点击这里来进行了解一下
在本节中,我将借用一个场景来对cucumber的一些特点来进行描述
HelloWorld
1.cucumber的目录结构
cucumber的执行需要特定的目录结构的。我们首先需要先创建这样的一个目录结构:
mkdir HelloWorld
cd HelloWorld
mkdir features
cd features
touch hello_cucumber.feature
mkdir step_definitions
cd step_definitions
touch hello_cucumber.rb通过上面的命令创建好如下图的目录层级结构:
在图中,HelloWorld这个目录下面包含了一个名为features目录,在features目录下面有一个名为hello_cucumber.feature的文件以及一个名为step_definitions的目录,在step_definitions这个目录下面有一个名为hello_cucumber.rb的文件。下面解释下各个目录以及文件的作用:
HelloWorld
这个根目录可以理解为工程所在的目录,存放了所有需要用到的文件和资源
features
这个目录下面包含了所有的场景文件和实现场景文件中描述的步骤文件
hello_cucumber.feature
这个文件包含了场景的描述,也就是对测试用例的描述,里面一般交代了测试的前提和测试需要的条件并且当发生某一事件的时候能够得到一个什么样的结果,这些描述一般使用很易懂的自然语言来进行描述它,所以技术或者非技术人员都能看懂
在features目录下可以包含一个或者多个feature文件,一般情况下,对于具有相同性质的测试场景会放到同一个feature文件中,以便于维护
step_definitions
这个目录包含了实现测试场景描述的步骤文件
hello_cucumber.rb
这个文件包含对应的测试场景的实现代码,这个步骤文件取决于你使用的什么语言,我这里是使用的ruby
2.代码
代码主要是包含在hello_cucumber.feature和hello_cucumber.rb文件中
hello_cucumber.feature
这里我们主要描述这样一个场景,以平常一个登陆系统来做为例子吧。在测试中的话,首先会有对这个登陆系统的描述和一些基本的需求。主要是作为一个登陆系统的使用者,希望登陆系统的运作正常。正常的使用中,一个登陆场景如下:
前置条件:进入到登陆页面
事件: 在用户名输入框输入正确的用户名,在密码框输入正确的密码,点击确定
预期结果:成功登陆
这是一个比较简单的测试用例,看看在cucumber中是如何实现它的。
首先我们先要将这个用例转换成cucumber所知道的描述语言,这部分描述是在feature文件中来进行实现的。代码如下:
Feature: Login
Login system should work fine Scenario: Login with right username and right password
Given I open the login page
When I set username with a right username
And I set password with a right password
And I click the login button
Then I see login success代码中的Feature,Scenario,Given,And,When,Then都是cucumber中的关键字,Feature说明了这个测试场景的大体情况和一些基本的描述,一般由需求人员和测试人员去完成,Scenario指明了具体场景的标题,以及这个场景是用来干什么的。Given给出了具体的测试场景的条件,When给出了事件,And表示一个连接,Then是预期的结果。在一个feature文件中可以包含多个Scenario。
hello_cucumber.rb
这个文件主要包含了feature文件中描述的场景的实现,代码如下
Given /^I open the login page$/ do
puts "open login page"
end When /^I set username with a right username$/ do
puts "set a right username"
end When /^I set password with a right password$/ do
puts "set a right password"
end When /^I click the login button$/ do
puts "click login button"
end Then /^I see login success$/ do
puts "login success"
end在feature文件中的每一个步骤都需要一个相应的ruby代码来与之对应,如果没有对应的实现步骤,则在执行用例的时候会出现找不到步骤的异常。在feature寻找步骤的时候,是通过正则表达式来进行匹配的,step文件中的Given /^...$/会匹配feature文件中符合这个正则的步骤。这个匹配是会忽略Given When之类的关键字的。如果在匹配的时候feature中的步骤没有找到step中对应的实现,则才执行的时候会报出忽略这一个步骤的异常而导致用户不会通过的。
3.运行用例
在命令行下进入到HelloWorld这个文件夹,然后输入命令 cucumber features/hello_cucumber.feature,结果如下:
从结果中看出,我们的用例全部的通过了。而且,我们在ruby文件(step文件)中的日志也都被打印出来了(天蓝色字)。
关于cucumber的命令,我会在后面仔细的来进行介绍的。
扩展
通过上面的例子,我们已经可以使用cucumber的基本功能去实现一些用例了。当然前提还需要你去了解一些自己熟悉的语言的一些测试框架,不然单纯的cucumber并不能起到太大的作用。
现在我们来进行扩展一下上面的需求。依旧是登录的例子。测试用例如下:
前置条件:进入到登陆页面
事件: 在用户名输入框输入正确的用户名,在密码框输入错误的密码,点击确定
预期结果:成功失败
根据刚刚所说的,写下的如下的feature:
Feature: Login
Login system should work fine Scenario: Login with right username and error password
Given I open the login page
When I set username with a right username
And I set password with a error password
And I click the login button
Then I see login fail对应的step如下:
Given /^I open the login page$/ do
puts "open login page"
end When /^I set username with a right username$/ do
puts "set a right username"
end When /^I set password with a error password$/ do
puts "set a error password"
end When /^I click the login button$/ do
puts "click login button"
end Then /^I see login success$/ do
puts "login fail"
end代码写到这里就完成了,但是软件工程中一个重要的思想是复用,相同的东西是否能进行提取呢?在上面的2个例子中,在设置密码这个地方,步骤基本是相同的,只是输入的值不一样,我们是否可以将这2个步骤合成一个呢?答案是可以的。修改设置密码的step:
When /^I set password with a (.*) password$/ do |password|
puts "set a #{password} password"
end经过这样的修改后发现feature中密码中输入步骤也能匹配到step对应的实现,而且能将right或者是error提取成一个参数传入到实现中。
feature中的参数化使得我们很少做很多的重复工作。
聪明的你又想起了另外的一个需求,比如我们的登录的例子需要在chrome和firefox上面去执行。也许你会想,我们直接把上面的第一步(打开浏览器进入login页)修改成匹配chrome和firefox的通用步骤,然后其他的copy一遍就ok。这样做是ok的,然而cucumber提供了一种更为聪明的方法来进行这个操作。
feature如下:
Feature: Login
Login system should work fine Scenario Outline: Login with right username and right password
Given I use <browser> open the login page
When I set username with a right username
And I set password with a right password
And I click the login button
Then I see login success Examples:
| browser |
| chrome |
| firefox |step如下:
Given /^I use (.*) open the login page$/ do |browser|
puts "use #{browser} open login page"
end When /^I set username with a right username$/ do
puts "set a right username"
end When /^I set password with a (.*) password$/ do |password|
puts "set a #{password} password"
end When /^I click the login button$/ do
puts "click login button"
end Then /^I see login success$/ do
puts "login success"
end在feature中,将前面Scenario改为了Scenario Outline,表示会有表格参数,参数使用<>来进行标注,在用例结束后Examples关键字中写入参数的具体值。这样后,在执行用例的时候,这个用例会被执行2次,每次执行会依次的采用Examples中的参数来进行执行,我们使用命令来执行看看结果:
从结果中可以看出我们执行了2个Scenario,打出的日志在Examples下面,第一个使用了chrome,第二个使用了firefox,和我们的预期是一样的。使用Examples能大幅的减轻我们的工作量。
在cucumber中还存在着另外一个table参数。我们看看他的使用场景。依旧是登录页,但是现在登录页和之前的不太一样,我们的系统是非常注重安全的,所以每一个用户登录的时候需要使用2个密码来进行登录,如果密码全部都正确才能登录成功。测试用例如下:
前置条件:进入到登陆页面
事件: 在用户名输入框输入正确的用户名,在第一个密码框输入正确的密码,在第二个密码框输入正确的密码,点击确定
预期结果:成功登录
先看看feature:
Feature: Login
Login system should work fine Scenario: Login with right username and right password
Given I open the login page
When I set username with a right username
And I set password
| id | value |
| password1 | value1 |
| password2 | value2 |
And I click the login button
Then I see login success在看看step:
Given /^I open the login page$/ do
puts "open login page"
end When /^I set username with a right username$/ do
puts "set a right username"
end When /^I set password/ do |table|
table.hashes.each do |item|
puts "set #{item["id"]} to #{item["value"]}"
end
end When /^I click the login button$/ do
puts "click login button"
end Then /^I see login success$/ do
puts "login success"
end在feature中,我们也使用了一个表格的形式,在step中可以通过一个参数直接获取到这个表格中的所有的参数,并且将他们存入到了hash中,而我们可以对这个hash进行操作,然后获取我们想要的值。
执行用例后如下:
可以看到结果和我们想要的是一样的。
在cucumber中有时候还会使用到步骤的组合。依旧采用登录这个例子。他里面所有的feature和使用的第一个例子一样。我们仔细想想里面的步骤中的第一步(打开登录页面),它实际是由打开浏览器和跳转到登录页面这2个步骤实现的,现在我们不改变feature,看看step中如何把这一步分解成为2步:
Given /^I open the login page$/ do
steps %{
Given I launch the browser
And I go to login page
}
end When /^I set username with a right username$/ do
puts "set a right username"
end When /^I set password with a right password/ do
puts "set a right password"
end When /^I click the login button$/ do
puts "click login button"
end Then /^I see login success$/ do
puts "login success"
end Given /^I launch the browser$/ do
puts "launch browser"
end Given /^I go to login page$/ do
puts "go to login page"
end在上面的step中,我们将之前的一步分解成了2步,这2步又被另外的一个step所调用。你也可以用下面的方式来实现它:
Given /^I open the login page$/ do
step "I launch the browser"
step "I go to login page"
end看看执行的结果:
结果如我们所预期的一样。
关于cucumber的基本语法就讲到这里了,如果感觉我有漏掉的希望大家可以提出。
Cucumber(2)——目录结构以及基本语法的更多相关文章
- II、Vue的项目目录结构 一些语法
Vue目录结构 这是某闭源项目的web端目录结构: 目录解析: -目录/文件 - build 项目构建(webpack)相关代码 config 配置目录.端口号:也有默认的 node_modules ...
- Markdown基本语法及生成目录结构的方法
Markdown是一种纯文本格式的标记语言.通过简单的标记语法,它可以使普通文本内容具有一定的格式. 一.标题 在想要设置为标题的文字前面加#来表示一个#是一级标题,二个#是二级标题,以此类推.支持六 ...
- Go 项目的目录结构 及 安装技巧
项目目录结构如何组织,一般语言都是没有规定.但 Go 语言这方面做了规定,这样可以保持一致性 1.一般的,一个 Go 项目在 GOPATH 下,会有如下三个目录: |--bin |--pkg |--s ...
- (五)Maven目录结构及常用命令说明
前面提到的部分知识有涉及到Maven目录结构与Maven常用的一些命令,在这里专门给大家做个简单的介绍. 1.Maven目录结构说明 Maven总体目录结构如下图: bin目录:该目录包含了mvn运行 ...
- 微信小程序购物商城系统开发系列-目录结构
上一篇我们简单介绍了一下微信小程序的IDE(微信小程序购物商城系统开发系列-工具篇),相信大家都已经蠢蠢欲试建立一个自己的小程序,去完成一个独立的商城网站. 先别着急我们一步步来,先尝试下写一个自己的 ...
- linux目录结构详细介绍
目录1.树状目录结构图2./目录3./etc/目录4./usr/目录5./var/目录6./proc/目录7./dev/目录 该文章主要来自于网络进行整理.目录结构参考地址:http://www.hu ...
- android源码的目录结构
android源码的目录结构 [以下网络摘抄] |-- Makefile ! l/ a5 n% S% @- `0 d# z# a$ P4 V3 o7 R|-- bionic ...
- linux专题一之文件管理(目录结构、创建、查看、删除、移动)
在linux系统中一切都是文件./ 在linux中为根目录,是一切文件的根目录.本文将通过linux系统的目录结构和与linux文件操作有关的相关命令(touch.mkdir.cp.mv.mv.les ...
- day 2 Linux目录结构
Linux系统的目录结构的基本介绍: 1)在逻辑上的所有目录(包括目录下的子目录)都在最高级别的目录“/”下. 根(/)目录是Linux系统中所有目录的起始点(顶点),根下面的目录及子目录是一个有层次 ...
随机推荐
- Magento2(麦进斗) docker 安装
Magento 介绍 Magento(麦进斗)是一套专业开源的电子商务系统,采用php进行开发,使用Zend Framework框架.Magento设计得非常灵活,具有模块化架构体系和丰富的功能.易于 ...
- 收藏 | 15 个你非了解不可的 Linux 特殊字符,妈妈再也不用担心我看不懂这些符号了!
不知道大家接触 Linux 系统有多久了,可曾了解过 Linux 中有哪些特殊的字符呢?其实啊,那些特殊字符都大有用处呢,今天的文章就给大家简单地科普一下 Linux 中你需要了解的 15 个特殊字符 ...
- 简述UDF/UDAF/UDTF是什么,各自解决问题及应用场景
UDF User-Defined-Function 自定义函数 .一进一出: 背景 系统内置函数无法解决实际的业务问题,需要开发者自己编写函数实现自身的业务实现诉求. 应用场景非常多,面临的业务不同导 ...
- 李宏毅老师机器学习课程笔记_ML Lecture 3-1: Gradient Descent
引言: 这个系列的笔记是台大李宏毅老师机器学习的课程笔记 视频链接(bilibili):李宏毅机器学习(2017) 另外已经有有心的同学做了速记并更新在github上:李宏毅机器学习笔记(LeeML- ...
- MATLAB中mean的用法
https://blog.csdn.net/wangyang20170901/article/details/78745587 MATLAB中mean的用法 转载仙女阳 最后发布于2017-12-07 ...
- 【深度强化学习】Curriculum-guided Hindsight Experience Replay读后感
目录 导读 目录 正文 Abstract[摘要] Introduction[介绍] 导读 看任何一个领域的文章,一定要看第一手资料.学习他们的思考方式,论述逻辑,得出一点自己的感悟.因此,通过阅读pa ...
- jmeter响应乱码(十四)
方法一: jmeter响应乱码解决方法:在jmeter的bin目录下找到jmeter.propertis这个文件,修改里面的#sampleresult.default.encoding=ISO-885 ...
- algorithm++:一个整数称为是:【幸运数】,如果这个整数的各位数字的平方和为1或者反复计算各位数字的平方和为1 例如 19 是个幸运数
1):一个整数称为是:[幸运数],如果这个整数的各位数字的平方和为1或者反复计算各位数字的平方和为1 例如 19 是个幸运数 coding:java程序实现 import org.junit.Test ...
- SpringCloud微服务架构和SOA架构
1,传统的三层架构 在传统的架构中,SSH,SSM,主要分为web 控制层,业务逻辑层,数据库访问层,单点项目,项目没有拆分,所有的开发任务全部写在一个项目中,耦合度比价高,如果程序中的一个功能出现了 ...
- Python python 五种数据类型--数字
一:Number 数字 不可变类型 整型(Int) - 通常被称为是整型或整数,是正或负整数,不带小数点. 长整型(long integers) - 无限大小的整数,整数最后是一个大写或小写的L.(P ...




