繼續推進之前,讓我們先寫一些測試吧!這隻API在完成前還會做很多的修改,我希望這些修改都可以由測試案例驅動。在zero2prod書中,這個階段從User Story出發先進行了一些整合測試,並且為了測試對程式碼進行了一些重構,將應用程式的進入點與核心功能拆成了main.rs
與startup.rs
兩個部份。書中的範例使用rust撰寫測試程式,在測試開發上只要使用cargo test
指令就可以輕鬆完成一次測試。然而,缺點是需要花比較多功夫在撰寫測試上,而我實在不願意為了測試跟編譯器打交道。因此,在這邊我選擇脫離了rust使用python來處裡整合測試的部份,順便熟悉一下另一種語言。
我使用poetry
來管理測試專案,在已經安裝好python的情況下依序執行:
//// 安裝poetry,安裝完畢後會指示將poetry加入shell環境中
curl -sSL https://install.python-poetry.org | python3 -
//// 初始化poetry專案
poetry init
//// 安裝pytest與requests
poetry add pytest requests
pytest是python常用的測試框架,而我們將使用它對API進行整合測試,所以要安裝requests,以便在測試中呼叫專案本身的API。
首先建立tests
資料夾來存放測試案例
因為我對python不熟悉,所以先來個簡單的測試,先新增health_test.py
來進行第一個測試
import requests
def test_health():
response = requests.get(f"http://localhost:3000/health_check")
assert response.status_code == 200
pytest會找出開頭為test
的方法進行測試我計畫在本地執行專案後呼叫 health_check,如果一切順利,應該會得到狀態碼 200。
//// 在本地端運行cargo專案
cargo run
//// 在poetry中運行測試
poetry run pytest
然後等待測試成功。
接下來新增subscribe_test.py
def test_subscribe_returns_a_200_for_valid_form_data():
username = "test_user_name"
response = requests.post(
f"http://localhost:3000/subscriptions",
headers={"Content-Type": "application/x-www-form-urlencoded"},
data={"name": username, "email": f"{username}@gmail.com"},
)
assert response.status_code == 200
理論上,這個測試也應該成功。
由於我不想在編寫測試時花太多時間,在整合測試中,我選擇了使用 Python。我嘗試過使用rust撰寫版本,兩者比較起來,由於rust更專注於安全性,為了完成測試就需要額外做很多的型別體操,好處是測試執行和開發之間可以流暢銜接。另一方面,Python 可以讓我更專注於測試本身,但需要先啟動專案然後再執行測試,操作上稍顯繁瑣,不過這一切在之後加入CI後差異就沒有那麼明顯了。