cucumber java 实例_cucumber java从入门到精通(3)简单实现及断言

cucumber java从入门到精通(3)简单实现及断言

上一节里我们定义了step的java代码实现文件,step就是测试步骤及断言的集合,我们先定义出来,以后可以驱动开发以及在持续集成时重用。

这一节我们将近距离细观一下所谓的step java实现。以下面的代码片段为例:

public class TodoStep { //1

@假设("^我的任务清单里有(\\d+)个任务$") //2

public void iHaveSomeTasks(int totalTasks) throws Throwable { //3

// Write code here that turns the phrase above into concrete actions

throw new PendingException(); //4

}

}

//1 定义了public class,这没什么好说的;

//2 假设注解,这个注解表明下面的方法对应的也就是feature文件中我的任务清单里有xxxx个任务这个步骤;

//3 定义了具体实现feature文件步骤的方法,并从feature定义中取得传入参数,也就是xxxx个任务的具体值;

//4 抛出Pending异常,表明该步骤暂未实现,但来日方长,也许有天可以实现;

cucmber执行顺序

如果你对上面的代码尚有疑问,那么是时候看一下cucumber的执行顺序了,以下面代码片段为例:

# feature

假设 我的任务清单里有3个任务 // 1

当 我完成1件任务之后 // 2

那么 我还剩下2件未完成的任务 //3

# step

@假设("^我的任务清单里有(\\d+)个任务$") //4

public void iHaveSomeTasks(int totalTasks) throws Throwable { //5

// Write code here that turns the phrase above into concrete actions

throw new PendingException();

}

@当("^我完成(\\d+)件任务之后$") //6

public void iFinishSomeTasks(int finishedTasks) throws Throwable { //7

// Write code here that turns the phrase above into concrete actions

throw new PendingException();

}

@那么("^我还剩下(\\d+)件未完成的任务$") //8

public void iLeftSomeTasks(int leftTasks) throws Throwable { //9

// Write code here that turns the phrase above into concrete actions

throw new PendingException();

}

当我们运行了run命令后(还记得上一节的run吗?其实就是执行了cucumber.api.cli.Main。),cucumber会去找feature文件,然后执行第1条feature语句,也就是//1

执行//1的时候,cucumber会去找对应的step定义文件,寻寻觅觅的过程中,cucumber发现了对应的注解,也就是//4

//4告诉cucumber,下面紧接着定义的那个方法就是该feature对应的代码实现,于是cucumber再去执行//5

在执行//5的时候,cucumber将3作为totalTasks这个参数传给//5

cucumber执行//5方法体中的内容并收到pending异常,于是该feature执行结束,转去执行下1条feature

小练习:你能自己说明//2以及//3的执行顺序吗

渐进重构之假装实现

回忆一下我们的测试目标,我们要测试一个todo list,第1步也就是在测试背景或者叫做前置条件里,我们是这样描述的

假设 我的任务清单里有3个任务 // 1

这时候不妨假设我们有个TodoList类,该类有个getTotalTaskCount()方法返回任务清单中一共有多少条任务。基于这个想法,我们重构一下TodoStep.java文件

@假设("^我的任务清单里有(\\d+)个任务$")

public void iHaveSomeTasks(int totalTasks) throws Throwable {

// totalTasks == 3

TodoList todo = new TodoList();

assertEquals(todo.getTotalTaskCount(), totalTasks);

}

在这里要说明的是注解中的(\d)表示获取feature定义中的数字字符并把该数字(int)作为totalTasks参数传入iHaveSomeTasks方法。因此totalTaks应该等于3。另外assertEquals是jUnit的断言方法

执行一下compile && run,得到下面的结果

step_definitions\TodoStep.java:11: 错误: 找不到符号

TodoList todo = new TodoList();

^

符号: 类 TodoList

位置: 类 TodoStep

step_definitions\TodoStep.java:11: 错误: 找不到符号

TodoList todo = new TodoList();

^

符号: 类 TodoList

位置: 类 TodoStep

2 个错误

我们无法编译,因为TodoList这个类并没有定义。

下面我们定义一下TodoList类。在implementation文件夹中新建1个名为TodoList.java的文件,该文件的实现是

// TodoList.java

package implementation;

public class TodoList {

public int getTotalTaskCount() {

return 3;

}

}

下面在TodoStep.java中导入TodoList类

// TodoStep.java

import implementation.TodoList;

修改一下compile文件,因为这次我们需要TodoList.java文件,修改完成的版本应该是这样的

# compile

javac -cp "./jars/*;." step_definitions\TodoStep.java implementation\TodoList.java

# linux && unix

javac -cp "./jars/*:." step_definitions\TodoStep.java implementation\TodoList.java

然后运行compile && run,得到下面的结果

#language: zh-CN

功能: 任务管理

场景: 完成1件任务 # todo.feature:5

假设我的任务清单里有3个任务 # TodoStep.iHaveSomeTasks(int)

当我完成1件任务之后 # TodoStep.iFinishSomeTasks(int)

cucumber.api.PendingException: TODO: implement me

at step_definitions.TodoStep.iFinishSomeTasks(TodoStep.java:19)

at ?.当我完成1件任务之后(todo.feature:7)

那么我还剩下2件未完成的任务 # TodoStep.iLeftSomeTasks(int)

1 Scenarios (1 pending)

3 Steps (1 skipped, 1 pending, 1 passed)

0m0.128s

cucumber.api.PendingException: TODO: implement me

at step_definitions.TodoStep.iFinishSomeTasks(TodoStep.java:19)

at ?.当我完成1件任务之后(todo.feature:7)

我们看到有1个step pass了,那就是我们刚定义前置条件step,所以到现在为止我们干的不错!我们有了feature文件,该文件描述了需求和测试用例,我们完成了测试step中的前置条件,并且我们实现了1个真正的TodoList类,尽管这个类目前还是嗷嗷待哺,不过当我们实现更多的step之后,TodoList类的功能会进一步完善,直到满足用户需求。实际上我们现在做的就是BDD,用测试去驱动开发。

可能有的同学会对此不屑一顾,TodoList类到目前为止只是自欺欺人的实现了1个返回int型数字3的方法,离我们所要的任务清单还相差十万八千里。其实不用担心这个,我们的TodoList类没有实现具体的功能是因为我们实现的测试步骤还不够多,我们接收到的需求还只是那么一点点,当我们实现更多步骤之后,TodoList自然会羽翼丰满。这就是所谓的最小实现原则。

渐进重构,重构剩下的2个步骤

下面我们重构剩下的2个步骤。

我们先假设TodoList有1个finishTask方法,每次调用这个方法就会完成n个任务,n从参数传入。于是剩余的任务就会减去n。

我们再假设TodoList有1个getRestTasksCount方法,调用这个方法可以获取剩下的task的数量。

重构完成以后,我们的代码如下所示

package step_definitions;

import cucumber.api.java.zh_cn.*;

import cucumber.api.PendingException;

import static org.junit.Assert.*;

import implementation.TodoList;

public class TodoStep {

TodoList todo;

@假设("^我的任务清单里有(\\d+)个任务$")

public void iHaveSomeTasks(int totalTasks) throws Throwable {

// Write code here that turns the phrase above into concrete actions

todo = new TodoList();

assertEquals(todo.getTotalTaskCount(), totalTasks);

}

@当("^我完成(\\d+)件任务之后$")

public void iFinishSomeTasks(int finishedTasks) throws Throwable {

// Write code here that turns the phrase above into concrete actions

todo.finisheTask(finishedTasks);

}

@那么("^我还剩下(\\d+)件未完成的任务$")

public void iLeftSomeTasks(int leftTasks) throws Throwable {

// Write code here that turns the phrase above into concrete actions

assertEquals(todo.getRestTasksCount(), leftTasks);

}

}

编译一下,不出意外的失败了,没关系,我们再去重构TodoList.java文件。

我们先实现finishedTask方法,这个方法的方法体是空,表示什么都不做;

然后实现getRestTasksCount方法,这个方法简单的返回2就好;

#TodoList.java

package implementation;

public class TodoList {

public int getTotalTaskCount() {

return 3;

}

public void finishTask(int count) {

}

public int getRestTasksCount() {

return 2;

}

}

再次运行compile && run

可以看到,我们的step全部运行通过了

#language: zh-CN

功能: 任务管理

场景: 完成1件任务 # todo.feature:5

假设我的任务清单里有3个任务 # TodoStep.iHaveSomeTasks(int)

当我完成1件任务之后 # TodoStep.iFinishSomeTasks(int)

那么我还剩下2件未完成的任务 # TodoStep.iLeftSomeTasks(int)

1 Scenarios (1 passed)

3 Steps (3 passed)

0m0.132s

总结

从这一节可以看到,我们的cucumber BDD行为驱动开发的流程是这样的:

Describe behaviour in plain text

Write a step definition in Java

Run and watch it fail

Write code to make the step pass

Run again and see the step pass

Repeat 2-5 until green like a cuke

小练习:翻译上面的6句话,弄清楚具体的意思。对照教程,请指出每一步与教程中所对应的代码

我们简单实现了TodoList类,目前的TodoList类是满足我们的feature的需求的。下一节我们将增加更多的测试数据,以便完善TodoList类。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里提供一个简单Cucumber Java 实例,用于说明如何使用 Cucumber 进行 BDD 测试。 假设我们要测试一个简单的计算器应用程序,其中包含加法和减法功能。 首先,我们需要创建一个 feature 文件(例如:calculator.feature),该文件描述了要测试的功能和场景。 ``` Feature: Calculator Scenario: Addition Given I have entered 50 into the calculator And I have entered 70 into the calculator When I press add Then the result should be 120 on the screen Scenario: Subtraction Given I have entered 90 into the calculator And I have entered 30 into the calculator When I press subtract Then the result should be 60 on the screen ``` 接下来,我们需要创建一个 step definition 文件(例如:CalculatorSteps.java),该文件包含了与 feature 文件中的步骤对应的 Java 代码。 ``` import cucumber.api.java.en.Given; import cucumber.api.java.en.When; import cucumber.api.java.en.Then; import cucumber.api.java.en.And; import static org.junit.Assert.*; public class CalculatorSteps { private Calculator calculator; private int result; @Given("^I have entered (\\d+) into the calculator$") public void i_have_entered_into_the_calculator(int arg1) throws Throwable { calculator = new Calculator(); calculator.enter(arg1); } @When("^I press add$") public void i_press_add() throws Throwable { result = calculator.add(); } @When("^I press subtract$") public void i_press_subtract() throws Throwable { result = calculator.subtract(); } @Then("^the result should be (\\d+) on the screen$") public void the_result_should_be_on_the_screen(int arg1) throws Throwable { assertEquals(arg1, result); } } ``` 在这个文件中,我们使用了 Cucumber 的注释(例如 @Given、@When、@Then 和 @And)来定义与 feature 文件中步骤相对应的方法。 最后,我们需要创建一个运行器(例如:RunCucumberTest.java),该运行器用于运行我们的测试用例。 ``` import cucumber.api.CucumberOptions; import cucumber.api.junit.Cucumber; import org.junit.runner.RunWith; @RunWith(Cucumber.class) @CucumberOptions(features = "classpath:calculator.feature") public class RunCucumberTest { } ``` 在这个文件中,我们使用了 Cucumber 的注释(例如 @CucumberOptions 和 @RunWith)来配置测试运行器。 现在,我们可以运行我们的测试用例,并检查它是否通过了所有的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值