前端的實作目前告一段落,我們將關注放到後端的部分。這次會直接使用 Grape 這個 Gem 來直接搭建 API 伺服器而不使用 Rails,並且刻意使用 Cucumber 來撰寫測試,在正常的狀況下只需要使用跟前端同一份即可,這次主要是展示針對後端可以怎樣實現。
初始化
我們可以用 bundle init
建立一個空的 Ruby 的專案,並且安裝所需的 Gem 來搭建環境。
修改 Gemfile
加入我們需要使用到的套件。
1# frozen_string_literal: true
2
3source 'https://rubygems.org'
4
5gem 'grape'
6gem 'puma'
7gem 'rack'
8
9group :development do
10 gem 'rubocop'
11end
12
13group :test do
14 gem 'cucumber'
15 gem 'rack-test'
16 gem 'rspec'
17end
運行 bundle install
安裝完畢後,我們再運行 bundle exec cucumber --init
將測試環境搭出來,並且加入一些用於測試的環境設定到 features/support/env.rb
裡面。
1ENV['RACK_ENV'] = 'test'
2
3require_relative '../../app'
4require 'rack/test'
5
6def app
7 Shop::API
8end
9
10World(Rack::Test::Methods)
這邊我們用 require_relative
去載入我們預定的主程式 app.rb
並且針對 rack-test
這個測試工具,定義一個在運行會用到的 app
方法,將 Shop::API
這個透過 Grape 來實現的 Rack 介面傳入,這樣我們就能在測試正常呼叫我們搭建的 API 伺服器。
撰寫測試
跟前端一樣,我們會先撰寫一個初始的測試來確認環境設定正確,加入 features/root.feature
來確認可以正常的取的一個 JSON API 回應。
1#language:zh-TW
2功能: Root
3 場景: 服務正常
4 當 我開啟 "/"
5 那麼 我會看到 JSON 屬性 "ok" 為真
這兩個步驟是還沒有被定義的,那麼繼續在 features/step_definitions/common.rb
裡面描述對應的行為。
1When('我開啟 {string}') do |path|
2 get path
3end
4
5Then('我會看到 JSON 屬性 {string} 為真') do |json_path|
6 json = JSON.parse(last_response.body)
7 path = json_path.split('.')
8
9 expect(json.dig(*path)).to be_truthy
10end
在這邊用了一個小技巧來檢查 JSON 的資料,因為我們經常會有巢狀的 JSON 內容,那麼可以利用 Ruby 的 #dig
方法來取得某個值,舉例來說。
1{
2 "name": "Aotoki",
3 "job": {
4 "title": "Senior Software Engineer",
5 "department": "Cloud Team"
6 }
7}
想要拿到 job
裡面的 title
可以用 json.dig('job', 'title')
這樣做,但是在 Cucumber 裡面都是純文字內容,因此可以用 job.title
的格式來描述,我們只需要在步驟定義上用 #split('.')
拆開即可。
實作功能
最後,我們要加上 app.rb
以及給 Rack 使用的 config.ru
讓我們可以實際的運行這個伺服器。
首先,在 config.ru
加入以下內容。
1# frozen_string_literal: true
2
3require_relative 'app'
4
5run Shop::API
這樣待會就可以用 bundle exec rackup
自動以 Puma 當伺服器啟動我們的後端 API 伺服器。
然後繼續加入 app.rb
定義一個全新的 API 並且回應我們預期的內容。
1# frozen_string_literal: true
2
3require 'bundler/setup'
4Bundler.require(:default, ENV['RACK_ENV'].to_sym)
5
6module Shop
7 # :nodoc:
8 class API < Grape::API
9 format :json
10
11 get do
12 { ok: true }
13 end
14 end
15end
完成一個最基礎的 API 實作後,我們就可以運行 bundle exec cucumber
來驗證結果,如果一切順利,就可以看到通過測試的訊息,我們就可以繼續後續跟前端整合的實作。
如果對這篇文章有興趣,可以透過以下連結繼續閱讀這系列的其他文章。
- 同時完成測試與文件 - Cucumber 的文件測試法
- 基本語法:功能描述 - Cucumber 的文件測試法
- 基本語法:驗證行為 - Cucumber 的文件測試法
- 基本語法:步驟定義 - Cucumber 的文件測試法
- 基本語法:輔助設定 - Cucumber 的文件測試法
- 前端環境:Vite 與 Cucumber - Cucumber 的文件測試法
- 商品列表與加入購物車 - Cucumber 的文件測試法
- 重構與移出購物車 - Cucumber 的文件測試法
- 商品資料與總價 - Cucumber 的文件測試法
- 結帳與結果 - Cucumber 的文件測試法
- 整理前端實作 - Cucumber 的文件測試法
- 初始化後端專案 - Cucumber 的文件測試法
- 商品資料 API - Cucumber 的文件測試法
- 更新購物車 API - Cucumber 的文件測試法
- 加入資料模型 - Cucumber 的文件測試法
- 持久化保存 - Cucumber 的文件測試法
- 結帳處理 - Cucumber 的文件測試法
- 在 Rails 的前後端分離 - Cucumber 的文件測試法
- 匯入前端實作 - Cucumber 的文件測試法
- 重現後端實作 - Cucumber 的文件測試法
- 累積價值 - Cucumber 的文件測試法