# 一起玩 Cypress(2) - 導入BDD工具Cucumber
###### tags: `Test` `Cypress`
## 介紹
Behaviour-Driven Development (BDD)以翻譯來說就是**行為驅動開發**,依據[Cucumber](https://cucumber.io/docs/bdd/)的介紹,測試雖然是其中一個重要項目但更重要的是縮小團隊之間的差距,其中有三個主要流程
1. Discovery:從[User Story](https://medium.com/3pm-lab/3-use-cases-for-writing-effective-user-stories-cd42625fef53)取得一個即將到來的變更,並討論其具體的功能需求。
2. Formulation:將需求寫成可被自動化執行的流程。
3. Automation:使用程式碼實踐文件內的操作描述,使其可以被自動化測試。
> 以上的介紹來自於[Cucumber](https://cucumber.io/docs/bdd/),這邊整理成自己方便理解的文字
其BDD要導入專案進行可能還牽扯專案管理相關的範疇,有興趣的人可以在多深入了解,這邊主要會專注功能描述撰寫流程及測試。
## 目錄
[TOC]
# 一、前言
延續上一篇文章的需求,完成測試之後又接到不同的需求,主要想要產出Cucumber的測試報告,使AWS在測試報告上支援`Cucumber JSON (.json)`格式,因此這篇文章就因此而誕生了,不過目前這邊不會講到測試報告產生及AWS上面的整合,只會專注在單純再導入`Cucumber`這一區塊。
# 二、實作步驟
因為是延續這邊就不再講解如何建立,想知道的可以參考[一起玩 Cypress(1) - 初探及快速建立](/OttG8UPkQE6ZuMUHrTVWZg)
## 環境建立
這邊我們使用套件[cypress-cucumber-preprocessor](https://github.com/badeball/cypress-cucumber-preprocessor)來快速架構,輸入以下指令進行安裝
```shell=
npm install @badeball/cypress-cucumber-preprocessor
```
安裝完成後`package.json`會出現安裝的套件和及版本
:::info
:bulb: **提示**: Cypress有再持續更新,參考時記得確認版本
:::

## 撰寫描述
這邊我們建立一個`google.feature`的描述檔
```gherkin=
# cypress/e2e/google.feature
Feature: Google.com
Scenario: visiting the google and then use search
When I visit google.com
And I type CypressTest in the box
And I click the search button
Then I should see a search result page
```
其句法是`Gherkin`這邊我們來簡單說明一下吧!
1. Feature: 主要用來分類`Scenario`和描述其整體軟體特徵
2. Scenario: 具體的例子來說明此業務功能,底下的組則為每一個執行步驟
步驟類別為如下
1. Given: 描述`Scenario`初始的內容
2. When: 描述事件或是行為
3. Then: 描述預期結果
4. And、But:如果有連續動作可以用此單字陳述分類
> 詳細內容可以參考官網[Gherkin Reference](https://cucumber.io/docs/gherkin/reference/)
## 撰寫測試
這邊不難看出撰寫的邏輯,這邊會看到步驟及描述就是用來對應我們程式碼的方式
```typescript=
// cypress/e2e/google.ts
import { When, Then, And } from "@badeball/cypress-cucumber-preprocessor";
When("I visit google.com", () => {
cy.visit('https://google.com');
});
And("I type Cypress in the box", () => {
cy.get('.gLFyf').type("CypressTest")
});
And("I click the search button", () => {
cy.get('.CqAVzb > center > .gNO89b').click()
});
Then("I should see a search result page", () =>{
cy.url().should('include', '/search')
});
```
## 環境設定
完整撰寫後測試腳本後目前尚未無法直接執,這邊有兩個問題需要處理
### 1. `Cypress`測試UI找不到檔案
預設測試檔案為`cypress/e2e/**/*.cy.{js,jsx,ts,tsx}`因此在測試畫面不會顯示`*.feature`的檔案

這邊比較簡單處理只需要前往設定檔`cypress.config.js`在對應的測試設定檔上調整檔案格式即可
```javascript=
// cypress.config.js
// ...
e2e: {
specPattern: "**/*.feature",
// ...其它設定
}
// ...
```
回到測試UI就可以看到檔案了

不過此時很開心的點進去會得到第二個錯誤畫面,其問題就是第二點描述的

### 2. 程式不知道怎麼運行`*.feature`
這邊就要使用`Webpack`來幫我們做些處理,步驟比較多不過跟著我的節奏往下走就會了
首先安裝[@cypress/webpack-preprocessor](https://github.com/cypress-io/cypress/tree/master/npm/webpack-preprocessor)插件
```shell=
npm install --save-dev @cypress/webpack-preprocessor
```
:::info
:bulb: 因為套件需要相依以下套件
* @babel/core
* @babel/preset-env
* babel-loader
* webpack
如果尚未安裝改成以下指令
```shell=
npm install --save-dev @babel/core @babel/preset-env babel-loader webpack
```
:::
安裝完成後接下來調整設定檔`cypress.config.js`加入前處理的流程,這邊直接附上完整代碼
```javascript=
const { defineConfig } = require("cypress");
const webpack = require('@cypress/webpack-preprocessor')
module.exports = defineConfig({
e2e: {
specPattern: "**/*.feature",
setupNodeEvents(on, config) {
const options = {
webpackOptions: {
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.feature$/,
use: [
{
loader: "@badeball/cypress-cucumber-preprocessor/webpack",
options: config,
},
],
},
],
},
},
};
on("file:preprocessor", webpack(options));
return config;
},
},
});
```
之後就可以透過UI進行測試流程了,結果如下圖可以發現左側結構變成我們撰寫的描述名稱,這樣不僅可以測試也可以很明確的知道哪一個行為開始出錯

最後在附上檔案結構提供參考

# 結論
Cucumber的加入如果單單專注在測試上面或許不是絕對必要的,因為前一篇[一起玩 Cypress(1) - 初探及快速建立](/OttG8UPkQE6ZuMUHrTVWZg)跟著實作後其實已經可以執行相關測試作業,Cucumber的導入個人感覺比較像是專案管理上的插件,管理人員透過撰寫描述文件可以清楚定義功能的每一步驟,後續開發人員可針對這些步驟撰寫對應的測試代碼,縮小雙方對於功能上的認知差異又可以變成日後的測試準則。
<br/>
---
相關參考來源:
[BDD/TDD差別是什麼? 手把手用 Cucumber 實作示範BDD](https://tw.alphacamp.co/blog/bdd-tdd-cucumber-behaviour-driven-development)
[Cucumber 入門筆記 (BDD自動化測試框架)](https://hackmd.io/@onejar99/BJ9LkkBNH#BDD)
<style>
code > span{ color: red;}
</style>