---
title: "同時完成測試與文件 - Cucumber 的文件測試法"
date: 2024-01-05T00:00:00+08:00
publishDate: 2024-01-05T00:00:00+08:00
lastmod: 2023-12-06T15:50:15+08:00
tags: ["Cucumber","教學","測試","文件","BDD"]
series: "test-with-cucumber"
toc: true
permalink: "https://blog.aotoki.me/posts/2024/01/05/test-with-cucumber-to-complete-test-and-document/"
language: "zh-tw"
---


在實際了解 Cucumber 的應用方式之前，我一直認為使用 Cucumber 撰寫測試是一件非常麻煩的事情，因為我們會需要實作許多 Step Definition（步驟定義）來讓文件中的某個行為可以被使用。

然而，當我了解到 Cucumber 的價值之後，就變成我優先選用的工具。

<!--more-->

## Behavior-Driven Development

在 [Cucumber 的官網](https://cucumber.io/)，明確地指出 Cucumber 是一種 Behavior-Driven Development（BDD，行為驅動開發）的工具，是以 [RSpec](https://rspec.info/) 為基礎發展而來，不同的地方在於 Cucumber 可以在不同語言中被使用。

測試軟體的手段有很多種類型，像是整合測試、功能測試、單元測試等等，對 BDD 來說主要會專注在「功能」上的測試，也因此 Cucumber 所使用的 Gherkin 語言副檔名都常會是 `.feature` 進行表示。

在我過去的經驗中，我們會在 Ruby on Rails 專案中優先對 Model 類型的物件進行單元測試，這是為了保護 Rails 中習慣將「商業邏輯」放在 Model 中的關係。然而，我們真的能透過單元測試將完整的功能還原嗎？更多的時候是無法的，這時候關注功能的 BDD 更能實現這件事情。

> RSpec 本身也是 BDD 框架，除此之外也很方便用來撰寫單元測試。

## 用文件溝通{#communication-with-documents}

雖然使用 RSpec 撰寫功能測試並不是問題，然而我們會面臨兩個困難。首先，如果遇到需要轉換語言的狀況，就需要完全重新開始。同時，在跟非 Ruby 工程師或者 PM（專案經理）、PO（專案負責人） 討論時，也會因為程式語言上的限制而卡住。

我們可以比較一下 RSpec 和 Cucumber 對同一個功能的呈現：

```ruby
RSpec.describe 'Simple Button' do
  before { get '/' }

  context 'when click button' do
    it 'is expected to display HI' do
      click_on 'Simple Button'
      expect(response).to have_text('HI')
    end
  end
end
```

```gherkin
Feature: Simple Button
	Scenario: Click button
	  When I click "Simple Button"
	  Then I can see "HI"
```

很明顯的，使用 Gherkin 能夠讓所有人很清楚的了解這個功能在使用上會有怎樣的效果，在跨團隊、職能的溝通上，可以有更好的效果。

> 在 Ruby 版本的 Cucumber 中，我們實際上還是會實際撰寫 `click_on 'Simple Button'` 這類實現，但是我們還能有一份文件用於溝通跟討論。

## 專注於功能{#focus-on-feature}

因為 Cucumber 天生是設計給功能的測試工具，我們也能更好的把注意力從單元層級提升到功能層級，在許多思考上也就比較不會迷失方向。

這在很多不同領域都也類似的觀點，像是在繪畫的時候我們會從草稿開始，調整到適合的狀態後再繼續加入細節。放到軟體開發上，即使我們實踐了 TDD（Test-Driven Development，測試驅動開發）卻把注意力放在一個小單元上，那麼實現的軟體會是許多破碎的類別（Class）所構成的。

如果把注意力放在功能上，我們會得到的是幾個有著不錯內聚的模組，同時在思考設計的時候，也能夠更加的全面去思考實作涵蓋的範圍，而不會讓單一類別非常完善，卻難以跟其他人協作。

