go golang database integration test mysql migration

不是有了 Unit Test 保證每一個 function 都正確的運作就好了嗎,為什麼會需要 Integration Test.

先來看幾個 Unit Test Success,但是 Integration Test Fail 的 Case



相信看完面的影片之後,你就會知道,為啥 Integration Test 很重要了


—— 這是分隔線 ——

Integration Test 跟 Unit Test 比較不同的是,你要怎樣重複執行 Test,而不會產生錯誤

這個有個範例,可以解釋重複執行時,會發生錯誤

Database 設計使用者名稱不能重複,我們測試增加使用者 Nick,第一輪 Test 會成功,第二輪就會失敗了

要避免這樣的問題,我們需要每次都提供全新的 Database 來避免這一個問題


—— 這是分隔線 ——

流程列出來如下

  • 建立新的 Database Server and Database

  • 執行 Migration

  • 放入測試用的資料

  • 開始測試

  • 移除 Database

  • 關閉 Database Server


1. 建立新的 Database Server and Database

這個時代 最快速的當然就是用 Docker 的技術來完成

我們使用 Docker-Compose 來完成,底下是 yaml 檔範例

version: "3.8"
services:
  db:
    image: mysql:8.0
    container_name: mysql-integration
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=integration
    ports:
      - "13306:3306"

version 決定了你可以使用哪些指令,但也跟你的 Docker 版本相關.版本對照

ports 是要特別注意的,如果你是在本地開發,你就會有跟你本地相同服務 Port 衝突的問題,若是遇到,就換個 port 吧

environment 裡面指定了 mysql root 帳號登入用的密碼,以及預設要建立的 Database

mysql 8.0 image 可以用的 environment 可以在 Docker-Hub mysql page 找到 Link


2. 執行 Migration

Migration 之於 Database,就像是 Source Code 之於 Git,如果你的 Database 沒有 Migration 的版本,在這個流程中,我們就無法建立整個所需要的 Table,以及放入運作所需的基本資料

個人是使用 migrate 來操作


3. 放入測試用的資料

你可以讀取檔案來下 SQL Query 你也可以把它寫成 Migration 計畫,跟著 migrate 一起跑(反正 migrate 就是在開 table 放資料,就跟著一起)


4. 開始測試

特別要注意的是,連上的這個臨時 DB 才是你要連接的 DB,不要弄錯了


5. 移除 Database

  db.Exec("DROP DATABASE " + databaseName).Error


6. 關閉 Database Server

當然 Docker 跑起來的服務,就把該 container 結束了就好


特別注意

忘了講很重要的步驟 2 ~ 5 都是要寫在 func TestMain(m *testing.M) 裡面

這是一個特別的 function,當你有這個 function 時,只會執行這個 function

還有 Docker 把各種 server 叫起來會需要時間,不能直接跑測試,需要等該服務可以操作了,才開始測試

最重要的是要使用 test tags,將 test 分類,千萬別在一般環境下,直接跑 integration Test.


DemoProject

Link



參考資料: Integration Testing Wiki