Background能够放置一些共有的描述,重构好帮手。
java
对于公用的Background,不会被多个scenario共享,每一个scenario会独立运行本身的Background,仅仅起到了代码复用的做用ios
Cucumber不建议Background涉及太多技术方面的描述,scenario也要简洁web
能够这么定义Data Tables
编程
Feature: Scenario: Given a board like this: | | 1 | 2 | 3 | | 1 | | | | | 2 | | | | | 3 | | | | When player x plays in row 2, column 1 Then the board should look like this: | | 1 | 2 | 3 | | 1 | | | | | 2 | x | | | | 3 | | | |
解析能够这么作api
import cucumber.api.java.en.*; import cucumber.api.PendingException; import cucumber.api.DataTable; import java.util.List; public class BoardSteps { private List<List<String>> board; @Given("^a board like this:$") public void aBoardLikeThis(DataTable table) throws Throwable { this.board = table.raw(); } @When("^player x plays in row (\\d+), column (\\d+)$") public void playerXPlaysInRowColumn(int arg1, int arg2) throws Throwable { System.out.println(board.toString()); throw new PendingException(); } @Then("^the board should look like this:$") public void theBoardShouldLookLikeThis(DataTable arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions // For automatic transformation, change DataTable to one of // List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>. // E,K,V must be a scalar (String, Integer, Date, enum etc) throw new PendingException(); } }
注意,传入的DataTable是不可变的,app
java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableList.set(Collections.java:1311) at tic_tac_toe.BoardSteps.playerXPlaysInRowColumn(BoardSteps.java:20) at *.When player x plays in row 2, column 1(tic_tac_toe.feature:8)
因此想增删改只能这么作dom
import cucumber.api.java.en.*; import cucumber.api.PendingException; import cucumber.api.DataTable; import java.util.ArrayList; import java.util.List; public class BoardSteps { private List<List<String>> board; @Given("^a board like this:$") public void aBoardLikeThis(DataTable table) throws Throwable { this.board = new ArrayList<List<String>>(); for (List<String> row : table.raw()) { this.board.add(new ArrayList<String>(row)); } } @When("^player x plays in row (\\d+), column (\\d+)$") public void playerXPlaysInRowColumn(int row, int col) throws Throwable { board.get(row).set(col, "x"); } @Then("^the board should look like this:$") public void theBoardShouldLookLikeThis(DataTable expectedTable) throws Throwable { expectedTable.diff(board); } }
Scenario Outline: Withdraw fixed amount Given I have <Balance> in my account When I choose to withdraw the fixed amount of <Withdrawal> Then I should <Outcome> And the balance of my account should be <Remaining> Examples: Successful withdrawal | Balance | Withdrawal | Outcome | Remaining | | $500 | $50 | receive $50 cash | $450 | | $500 | $100 | receive $100 cash | $400 | Examples: Attempt to withdraw too much | Balance | Withdrawal | Outcome | Remaining | | $100 | $200 | see an error message | $100 | | $0 | $50 | see an error message | $0 |
惋惜cucumber貌似不支持header和bottom的过滤,因此手动筛选ide
@When("^I need a table$") public void doSomething(DataTable dataTable) throws Throwable { List<List<String>> rows = dataTable.asLists(String.class); // Either quit having a header in your datatable or remove the first row rows.remove(0); for (List<String> row : rows) { ... } }
Scenario: Ban Unscrupulous Users When I behave unscrupulously Then I should receive an email containing: """ Dear Sir, Your account privileges have been revoked due to your unscrupulous behavior. Sincerely, T he Management """ And my account should be locked
顾名思义,使用Tags和子文件夹维护项目结构
工具
做者说,想当年Cucumber仍是个叫RSpec Story Runner的工具,使用.story的后缀名,是否是很像Agile里的user story?做者说后来认为user story脱离于代码,且伴随着user story的变化,理应不影响cucumber中现有的feature,因此推荐不要混淆,即便要引入story的思惟,也应该用tag测试
The features should describe how the system behaves today, but they don’t need to document the history of how it was built; that’s what a version control system is for!
将@keyword置于Feature或者Scenario以前,即是Tag
@nightly @slow Feature: Nightly Reports @widgets Scenario: Generate overnight widgets report ... @doofers Scenario: Generate overnight doofers report
三个用处:
Documentation:标记标识
Filtering:运行或生成报表时的筛选
Hooks:部分运行
Symptom | Problem |
Some of our tests fail randomly. | Flickering scenarios |
We keep breaking tests unintentionally. | Brittle features |
Our features take too long to run. | Slow features |
Our stakeholders don’t read our features. | Bored stakeholders |
Flickering scenarios就是莫名其妙地时好时坏的test case,最多见的有三种:
Shared Environments
Leaky Scenarios
Race Conditions and Sleepy Steps
固然,做者也说,要是真轮到你改bug,实在是找不出方法了,那就把这个test case删掉...
Brittle features就是那些不得不作的却不相干的事
一般有这些可能:
Fixture Data
Duplication
Leaky Scenarios
Tester Apartheid
SLOW FEATURES
这个没啥好说的,慢呗,做者建议真遇到了,能够试试tag+并行
Race Conditions and Sleepy Steps
Lots of Scenarios
Big Ball of Mud
BORED STAKEHOLDERS
貌似就是在说产品经理和开发测试之间的隔膜...
常见的来源以下:
Incidental Details
Imperative Steps
Duplication
Ubiquitous What?
Siloed Features
做者强调Cucumber features就是living documentation
Living: It tests the system automatically so you can work on it safely.
Documentation: It facilitates good communication about the current or planned behavior of the system.
Scenario要写的直观相关简洁
Bad:
Scenario: Check inbox Given a User "Dave" with password "password" And a User "Sue" with password "secret" And an email to "Dave" from "Sue" When I sign in as "Dave" with password "password" Then I should see 1 email from "Sue" in my inbox
Well:
Scenario: Check inbox Given I have received an email from "Sue" When I sign in Then I should see 1 email from "Sue" in my inbox
做者说了命令式编程(Imperative Programming) 和 声明式编程(Declarative Programming)。
Gherkin是命令式的,可是推荐采用声明式的方式去写
做者说 ”想当年我跟Martin Fowler结对编程的时候,受益不浅!“, 强调DAMP principle: Descriptive and Meaningful Phrases和DRY principle (Don’t Repeat Yourself)
Three Amigos
Three Amigos
The best Gherkin scenarios are created when the three amigos come together, bringing three very different perspectives:
The first amigo is a tester, who thinks about how to break things. The tester will typically come up with lots of scenarios, sometimes covering obscure edge cases and sometimes covering very important ones that no one else had thought of.
The second amigo is a programmer, who thinks about how to make things. The programmer will typically add steps to scenarios, as he asks clarifying questions about what exactly should happen. The third amigo is the product owner, who cares about scope. When the tester thinks of scenarios that hit edge cases the product owner doesn’t care about, she can tell the team to drop that scenario out of scope altogether, or the group can decide to test it with unit tests only. When the programmer explains that implementing a particular scenario will be complicated, the product owner has the authority to help decide on alternatives or to drop it altogether.
Many teams practicing BDD have found the three amigos make a great partnership for thrashing out Gherkin scenarios that the whole team believes in. You don’t have to stop at three amigos, though: invite your team’s user experience specialists or operations staff, for example, if the feature being discussed will affect them.
同上一节,讲了一些问题和解决办法
LEAKY SCENARIOS --〉Test Data Builders
RACE CONDITIONS AND SLEEPY STEPS --〉introduce a fixed-length pause, or sleep
SHARED ENVIRONMENTS --〉 One-Click System Setup
Tester Apartheid --〉 delegate the work of running basic checks to Cucumber
FIXTURE DATA --〉 Nightly Build
LOTS OF SCENARIOS --〉subfolders + tags
BIG BALL OF MUD --〉包含上述多种问题,要确保可测
扯了些管理学的故事和理念
Stop the Line
大野耐一(Taiichi Ohno 1912-1990) Stop the Line at Toyota
DEFECT PREVENTION 四要素
Detect the abnormality.
Stop what you’re doing.
Fix or correct the immediate problem.
Investigate the root cause and install a countermeasure.
第一部分Cucumber fundamentals 就结束了。
做者反复强调 Scenario要写出declarative style