The Cucumber for Java Book讀書筆記[二]

Part 5 Expressive Scenarios

Background

Background能夠放置一些共有的描述,重構好幫手。
java

對於公用的Background,不會被多個scenario共享,每一個scenario會獨立運行本身的Background,僅僅起到了代碼複用的做用ios

Cucumber不建議Background涉及太多技術方面的描述,scenario也要簡潔web

Data Tables

能夠這麼定義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
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) {
            ...
        }
    }
Doc Strings
 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


Staying Organized with Tags and Subfolders

顧名思義,使用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:部分運行

Part 6 Keeping Your Cucumbers Sweet

Feeling the Pain


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


Working Together

做者強調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.

Caring for Your Tests

同上一節,講了一些問題和解決辦法

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 and Defect Prevention

扯了些管理學的故事和理念

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

相關文章
相關標籤/搜索