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系统中所有目录的起始点(顶点),根下面的目录及子目录是一个有层次 ...
随机推荐
- SpringFramework之IoC容器初始化
分析例子 启动类 Application,使用的是ClassPathXmlApplicationContext来加载xml文件 /** * @author jianw.li * @date 2020/ ...
- tigervnc使用总结
vncserver和x0vncserver用法总计 通常vncserver :port 会调用到xvnc,这时系统会新建一个虚拟桌面通过vncserver分享出去. vncserver的用法很简单: ...
- 常见Web安全漏洞--------sql注入
SQL注入:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库执行一些恶意的操作.在mybatis 中比较容易出现:${} 会发生sql 注入问题 #{}: 解析为一个 JDBC 预编译语句(p ...
- Ubuntu 18 安装MySQL 5.7
1.首先把系统换到阿里云的镜像源,需要等待一会 2.系统更新完毕后执行MySQL安装命令:sudo apt install mysql-server 3.查看MySQL服务状态:sudo servic ...
- 实验四 数据查询3-group by等
实验四 数据库查询 一. 实验内容: 1. Group by语句 2. Having 语句 3. Order by语句 4. Limit语句 5. Union语句 6. Handler语句 二. ...
- 基于Asp.Net Core,利用ZXing来生成二维码的一般流程
本文主要介绍如何在.net环境下,基于Asp.Net Core,利用ZXing来生成二维码的一般操作.对二维码工作原理了解,详情见:https://blog.csdn.net/weixin_36191 ...
- 从零开始,做一个简单的Vuetify项目,图标安装成功
安装Vuefity的时候,碰到一些坑,经过一番折腾,终于成功,记录正确的姿势如下: 创建一个Vue项目: vue init webpack-simple vular-admin 进入项目目录: cd ...
- 3NF的无损连接和保持函数依赖的分解、BCNF的无损连接的分解
首先,需要了解3NF.BCNF范式的要求. 3NF:不存在非主属性对码的传递函数依赖或部分函数依赖. 如AB-C,A->C 码为(A,B),A,B是主属性,C是非主属性,C部分函数依赖于码,即 ...
- 1029 Median (25分)
Given an increasing sequence S of N integers, the median is the number at the middle position. For e ...
- Scratch2的鸡兔同笼
解题思路鸡兔同笼新算法:已知共有鸡和兔15只,共有40只脚,问鸡和兔各有几只.算法:假设鸡和兔训练有素,吹一声哨,它们抬起一只脚,(40-15=25) .再吹一声哨,它们又抬起一只脚,(25-15=1 ...