cucumber作为BDD(行为驱动测试)的自动化测试工具,可以很好的帮助进行功能测试。它将功能拆分为一个个的场景(可以理解为小功能点),每个场景内可以独立的做数据初始,然后再对初始的数据进行测试,检测是否达到预期的效果。下面将从java的角度,对cucumber的使用进行说明。(为了方便起见,这边只对代码做简单的说明,完整的代码在最后以链接的形式提供下载。)
一、例子说明
下面对职员的新增和根据年龄搜索满足条件的职员进行测试,几个类的代码如下:
首先定义的职员的model:
package com.zzq.test.cucumber.staff;
import java.io.Serializable;
public class Staff implements Serializable {
private static final long serialVersionUID = -1617670200520139146L;
private String name;
private int age;
private String address;
public Staff(){
}
public Staff(String name, int age, String address) {
super();
System.out.println("init data,name:"+name+",age:"+age+",address:"+address);
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
紧接着写了个职员的操作类StaffManager,如下:
package com.zzq.test.cucumber.staff;
import java.util.ArrayList;
import java.util.List;
public class StaffManger {
private List<Staff> staffList = new ArrayList<Staff>();
public void addStaff(Staff staff){
staffList.add(staff);
}
public List<Staff> findByAge(int min,int max){
List<Staff> retList = new ArrayList<Staff>();
for(Staff staff:staffList){
if(staff.getAge()>=min&&staff.getAge()<=max){
retList.add(staff);
}
}
return retList;
}
}
接着对StaffManager的测试步骤(方法)进行定义,其中@Given的部分代表为测试执行的时候会调用初始的,@Then的部分代表测试的时候会用于检验数据/逻辑是否正确:
package com.zzq.test.cucumber.staff;
import java.util.List;
import org.junit.Assert;
import com.zzq.test.cucumber.staff.Staff;
import com.zzq.test.cucumber.staff.StaffManger;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
public class StaffSteps {
private StaffManger manager = new StaffManger();
@Given("姓名:(.+),年龄:(\\d+),地址:(.+)")
public void addStaff(String name,int age,String address){
Staff staff = new Staff(name,age,address);
manager.addStaff(staff);
}
@Then("年龄在(\\d+)~(\\d+)的职员有(\\d+)个")
public void findByAge(int min,int max,int size){
List<Staff> list = manager.findByAge(min, max);
Assert.assertEquals(list.size(), size);
}
}
接下来定义场景Staff.feature,Given的部分与上面步骤定义的@Given对应,通过正则表达式来匹配;Then的部分与上面的@Then部分匹配。:
Feature:测试职工相关的功能
Scenario:测试根据年龄查找职工
Given 姓名:漫天的沙,年龄:18,地址:厦门市思明区
And 姓名:小明,年龄:30,地址:北京市朝阳区
And 姓名:李雷,年龄:25,地址:漳州漳浦县
And 姓名:小红,年龄:20,地址:江西省
Then 年龄在20~30的职员有3个
Then 年龄在23~30的职员有2个
接下来写一个测试的入口类:
package com.zzq.test.cucumber.staff;
import org.junit.runner.RunWith;
import cucumber.api.junit.Cucumber;
@RunWith(Cucumber.class)
public class StaffTest {
}
执行类,junit的运行结果如下:
控制台执行结果如下:
二、分析
上述的代码,首先入口类需要声明@RunWith(Cucumber.class),该类存在于cucumber-junit的jar包内,声明之后会自动搜索classpath下所有声明为@Given和@Then以及场景的文件。之后对搜索到的内容进行处理,根据@Given注解的内容到搜索到的场景文件的内容进行正则匹配,如果匹配到则调用该方法(正常情况下用于数据初始);如果为@Then注解,同样的正则匹配查找,然后根据设置的参数match groups,设置对应的参数,然后传参进行校验。需要注意以下几个事项:
(1)如果feature文件与测试的Steps类不在同个目录下,需要通过@CucumberOptions注解进行指定,否则会找不到feature文件导致用例没执行(不会报错);
(2)feature文件中的Scenario、Given、And和Then均为关键字。其中Scenario代表为场景的开始,后可以跟一句话进行描述;接下来定义Given,对数据进行初始化;接着定义Then,Then用于校验的时候使用。
完整代码:完整代码