url: /posts/6157d87338ce894d18c013c3c4777abb/
title: 如何用GitHub Actions為FastAPI項目打造自動化測試流水線?
date: 2025-09-15T05:16:10+08:00
lastmod: 2025-09-15T05:16:10+08:00
author: cmdragon
summary:
持續集成(CI)是一種自動化開發實踐,通過自動運行測試和代碼檢查來驗證代碼變更的正確性。GitHub Actions 是 GitHub 的自動化工具,用於實現 CI/CD 流程,核心概念包括工作流、事件、作業、步驟和動作。FastAPI 項目通過標準化的項目結構和 pytest 測試用例,結合 GitHub Actions 搭建自動化測試流水線,確保代碼質量和兼容性。流水線通過 Push 或 PR 觸發,自動安裝依賴、運行測試和檢查代碼風格,幫助開發者提前發現問題,提升開發效率。
categories:
- fastapi
tags:
- 持續集成
- GitHub Actions
- FastAPI
- 自動化測試
- pytest
- CI/CD
- 代碼質量
<img src="https://s.coze.cn/t/Zt07Ru6NDzs/" title="cmdragon_cn.png" alt="cmdragon_cn.png"/>
<img src="https://api2.cmdragon.cn/upload/cmder/20250304_012821924.jpg" title="cmdragon_cn.png" alt="cmdragon_cn.png"/>
掃描二維碼關注或者微信搜一搜:編程智域 前端至全棧交流與成長
發現1000+提升效率與開發的AI工具和實用程序:https://tools.cmdragon.cn/
1. 持續集成與GitHub Actions基礎
1.1 什麼是持續集成(CI)?
持續集成(Continuous Integration,簡稱CI)是一種自動化開發實踐:每當開發者向代碼倉庫推送(Push)或提交合並請求(Pull Request)時,系統會自動運行一系列預先定義的流程(如安裝依賴、運行測試、檢查代碼風格),快速驗證代碼變更的正確性。
對於FastAPI項目,CI的核心價值是:
- 避免“集成地獄”:儘早發現代碼中的bug(比如API端點邏輯錯誤、依賴衝突);
- 保證代碼質量:強制遵循團隊代碼規範(如PEP 8);
- 加速協作:合併請求時自動驗證,減少人工review的負擔。
1.2 GitHub Actions 核心概念快速理解
GitHub Actions是GitHub內置的自動化工具,用於實現CI/CD流程。你可以把它想象成一個“自動化機器人”,根據你寫的“指令清單”(工作流文件)執行任務。以下是幾個關鍵概念:
- 工作流(Workflow):一個完整的自動化流程(如“運行FastAPI測試”),用YAML文件定義,存放在項目根目錄的
.github/workflows/下; - 事件(Event):觸發工作流的“開關”(如Push代碼、提交PR);
- 作業(Job):工作流中的獨立任務(如“安裝依賴”“運行測試”),默認並行執行;
- 步驟(Step):作業中的具體操作(如“拉取代碼”“運行pytest”),順序執行;
- 動作(Action):可複用的“代碼塊”(如
actions/checkout@v4用於拉取代碼),避免重複造輪子。
2. FastAPI項目初始化與測試準備
在搭建CI流水線前,我們需要先準備一個標準化的FastAPI項目結構,並編寫可自動化的測試用例。
2.1 標準項目結構設計
一個清晰的項目結構能讓CI流程更易維護,推薦結構如下:
fastapi-ci-demo/ # 項目根目錄
├── app/ # 應用核心代碼目錄
│ ├── __init__.py # 標識app為Python模塊
│ └── main.py # FastAPI主程序
├── tests/ # 測試用例目錄
│ ├── __init__.py # 標識tests為Python模塊
│ └── test_api.py # API測試用例
├── requirements.txt # 依賴清單(或用pyproject.toml+Poetry)
└── .flake8 # flake8代碼風格配置文件
2.2 編寫FastAPI核心代碼
我們以“用户管理API”為例,編寫app/main.py:
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr # 導入Pydantic類型
# 1. 初始化FastAPI應用
app = FastAPI(title="用户管理API", version="1.0")
# 2. 定義數據模型(Pydantic v2)
class UserCreate(BaseModel):
name: str # 用户名:必填,字符串
email: EmailStr # 郵箱:必填,符合郵箱格式(如xxx@example.com)
age: int | None = None # 年齡:可選,整數
# 3. 模擬數據庫(實際項目用SQLAlchemy/Redis)
users_db = []
# 4. 定義API端點
@app.post("/users/", response_model=UserCreate)
def create_user(user: UserCreate):
"""創建用户:接收UserCreate模型數據,存入模擬數據庫"""
users_db.append(user.model_dump()) # 將Pydantic模型轉為字典存庫
return user # 返回創建的用户數據(自動序列化為JSON)
關鍵説明:
- 使用Pydantic v2的
BaseModel定義數據模型,自動完成請求數據的驗證; response_model指定端點的返回格式,確保返回數據符合UserCreate規則;- 模擬數據庫
users_db用於快速測試,實際項目需替換為真實數據庫(如PostgreSQL)。
2.3 用pytest編寫測試用例
測試是CI的核心,我們用pytest+FastAPI TestClient編寫測試用例(tests/test_api.py):
from fastapi.testclient import TestClient # 導入TestClient用於模擬HTTP請求
from app.main import app # 導入FastAPI應用實例
# 創建TestClient實例(相當於“模擬瀏覽器”)
client = TestClient(app)
def test_create_user_success():
"""測試:成功創建用户(預期200 OK)"""
test_data = {
"name": "張三",
"email": "zhangsan@example.com",
"age": 28
}
# 發送POST請求到/users/端點,用json參數傳遞JSON數據
response = client.post("/users/", json=test_data)
# 斷言:狀態碼是200,返回數據與測試數據一致
assert response.status_code == 200
assert response.json() == test_data
def test_create_user_missing_email():
"""測試:缺少必填字段email(預期422驗證錯誤)"""
test_data = {
"name": "李四",
"age": 30
}
response = client.post("/users/", json=test_data)
# 斷言:狀態碼是422,錯誤信息包含“email”字段
assert response.status_code == 422
assert "email" in response.json()["detail"][0]["loc"]
def test_create_user_invalid_email():
"""測試:郵箱格式無效(預期422驗證錯誤)"""
test_data = {
"name": "王五",
"email": "wangwu.example.com", # 缺少@符號
"age": 25
}
response = client.post("/users/", json=test_data)
assert response.status_code == 422
assert "email" in response.json()["detail"][0]["loc"]
關鍵説明:
TestClient能模擬真實HTTP請求,無需啓動Uvicorn服務器;- 測試用例覆蓋了正常場景(成功創建)和異常場景(缺少字段、格式錯誤),確保API的魯棒性;
- 使用
assert語句驗證結果,pytest會自動識別並運行這些用例。
2.3 依賴清單與版本管理
在requirements.txt中列出項目依賴(需使用最新穩定版,可通過PyPI查詢):
# FastAPI核心依賴
fastapi==0.104.1
uvicorn==0.24.0.post1 # ASGI服務器
# 測試依賴
pytest==7.4.3 # 測試框架
requests==2.31.0 # HTTP請求庫(TestClient依賴)
# 代碼風格檢查
flake8==6.1.0 # 代碼風格檢查工具
# Pydantic
pydantic==2.5.2 # Pydantic v2最新版
3. GitHub Actions自動化測試流水線搭建
現在,我們編寫工作流文件(.github/workflows/ci.yml),告訴GitHub Actions要做什麼。
3.1 工作流文件基礎結構
一個完整的CI工作流文件包含以下部分:
name: FastAPI CI # 工作流名稱(顯示在GitHub Actions頁面)
on: # 觸發條件:Push或PR到main分支時運行
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs: # 作業列表:一個工作流可包含多個作業
build: # 作業名稱:“構建與測試”
runs-on: ubuntu-latest # 運行環境:Ubuntu最新版虛擬機
steps: # 作業步驟:順序執行
# 步驟1:拉取代碼到虛擬機
- name: Checkout code
uses: actions/checkout@v4 # 官方動作:拉取代碼
# 步驟2:設置Python環境
- name: Set up Python 3.11
uses: actions/setup-python@v5 # 官方動作:安裝Python
with:
python-version: "3.11" # 指定Python版本(FastAPI支持3.8+)
cache: "pip" # 緩存pip依賴,加速後續運行
# 步驟3:安裝項目依賴
- name: Install dependencies
run: | # 運行命令行指令
python -m pip install --upgrade pip # 升級pip
pip install -r requirements.txt # 安裝依賴
# 步驟4:運行pytest測試
- name: Run tests
run: pytest tests/ -v # 運行tests目錄下的所有測試,-v顯示詳細輸出
# 步驟5:檢查代碼風格(flake8)
- name: Check code style
run: flake8 app/ tests/ # 檢查app和tests目錄下的代碼
3.2 配置説明與擴展
- 觸發條件:
on.push.branches: [ "main" ]表示只有Push到main分支才觸發;若想讓develop分支也觸發,可添加"develop"; - Python版本:
setup-python動作支持多個Python版本(如3.10、3.11),可添加matrix參數實現多版本測試(見擴展部分); - 緩存依賴:
cache: "pip"會緩存~/.cache/pip目錄,避免每次重新下載依賴,大幅加快運行速度; -
代碼風格檢查:
flake8會按照.flake8配置文件的規則檢查代碼,示例.flake8配置:[flake8] max-line-length = 120 # 允許最長行120字符(默認79) exclude = .git,__pycache__,venv/ # 排除不需要檢查的目錄
3.3 擴展:多Python版本測試
若想驗證FastAPI在多個Python版本下的兼容性,可添加matrix參數:
jobs:
build:
runs-on: ubuntu-latest
strategy: # 策略:多版本並行測試
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"] # 測試4個Python版本
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} # 動態使用Python版本
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
# 後續步驟與之前一致...
4. 流水線運行與結果驗證
當你將代碼Push到GitHub的main分支(或提交PR到main),GitHub Actions會自動觸發工作流。你可以在GitHub倉庫的Actions標籤頁中查看運行結果:
4.1 查看運行日誌
點擊具體的工作流運行記錄(如“Push to main by Alice”),可以看到每個步驟的詳細日誌:
- 若所有步驟顯示綠色的“√”,説明流水線運行成功;
- 若某步驟顯示紅色的“×”,説明該步驟失敗(如pytest測試不通過),點擊該步驟可查看錯誤詳情。
4.2 失敗場景分析與修復
以“pytest測試失敗”為例,假設test_create_user_missing_email用例失敗,日誌顯示:
AssertionError: assert 200 == 422
這説明缺少email字段時,API返回了200而不是預期的422。原因可能是UserCreate模型中的email字段被誤設為可選:
# 錯誤寫法(email可選)
class UserCreate(BaseModel):
email: EmailStr | None = None # 錯誤:| None = None讓email可選
修復方法:去掉| None = None,讓email成為必填字段:
# 正確寫法(email必填)
class UserCreate(BaseModel):
email: EmailStr # 正確:無默認值,必填
修改後重新Push代碼,CI流水線會再次運行,測試用例將恢復正常。
5. 課後Quiz:鞏固你的CI知識
問題1
如何修改工作流配置,讓流水線在Push到develop分支或提交PR到main分支時觸發?
答案:
on:
push:
branches: [ "main", "develop" ] # Push到main或develop觸發
pull_request:
branches: [ "main" ] # PR到main觸發
問題2
FastAPI中用TestClient測試POST請求時,為什麼推薦用json參數而不是data參數?
答案:
json參數會自動將Python字典轉為JSON字符串,並設置請求頭Content-Type: application/json(FastAPI默認接收JSON);而data參數會將數據作為表單提交(Content-Type: application/x-www-form-urlencoded),不符合API的預期格式。
問題3
若pytest運行時提示“ModuleNotFoundError: No module named 'app'”,可能的原因是什麼?
答案:
Python的模塊搜索路徑未包含項目根目錄。解決方法:
- 確保運行pytest時的當前目錄是項目根目錄(如
fastapi-ci-demo/); - 在
tests目錄下創建__init__.py,標識tests為Python模塊; - 運行pytest時添加
--rootdir參數:pytest --rootdir . tests/。
6. 常見報錯與解決方案
在CI流水線運行中,你可能會遇到以下常見錯誤,提前掌握解決方案能節省大量時間。
報錯1:422 Validation Error(測試或API請求中)
- 原因:請求數據不符合Pydantic模型的驗證規則(如缺少必填字段、類型錯誤);
-
解決步驟:
- 查看響應的
detail字段(如response.json()["detail"]),找到錯誤位置(loc字段)和原因(msg字段); - 修改請求數據,使其符合模型規則(如補充缺少的
email字段);
- 查看響應的
- 預防建議:編寫測試用例時覆蓋所有異常場景(如缺少字段、格式錯誤)。
報錯2:pytest找不到測試用例(collected 0 items)
- 原因:測試文件/函數的命名不符合pytest的默認規則(文件以
test_開頭/結尾,函數以test_開頭); -
解決步驟:
- 將測試文件重命名為
test_api.py(而非api.py); - 將測試函數重命名為
test_create_user(而非create_user);
- 將測試文件重命名為
- 預防建議:遵循pytest命名規範,避免手動指定測試文件路徑。
報錯3:GitHub Actions中“Install dependencies”失敗
-
原因:
requirements.txt中的版本號錯誤(如fastapi==999.0,不存在的版本);- pip源無法訪問(如默認源被牆);
-
解決步驟:
- 驗證依賴版本(通過PyPI查詢最新版);
-
更換pip源(如使用阿里雲源):
- name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
附:CI流水線流程圖
通過以上步驟,你已經掌握瞭如何用GitHub Actions為FastAPI項目搭建自動化測試流水線。CI的核心價值是“提前發現問題”,它能讓你在代碼合併前就消滅bug,大幅提升項目的穩定性和開發效率。
下一步,你可以嘗試擴展流水線功能,比如:
- 自動部署FastAPI到雲服務器(如AWS EC2、Vercel);
- 生成測試覆蓋率報告(用
pytest-cov); - 發送Slack/釘釘通知(用
act1ons/slack@v3)。
祝你在FastAPI的CI之路上越走越順!
餘下文章內容請點擊跳轉至 個人博客頁面 或者 掃碼關注或者微信搜一搜:編程智域 前端至全棧交流與成長,閲讀完整的文章:如何用GitHub Actions為FastAPI項目打造自動化測試流水線?
<details>
<summary>往期文章歸檔</summary>
- 如何用Git Hook和CI流水線為FastAPI項目保駕護航? - cmdragon's Blog
- FastAPI如何用契約測試確保API的「菜單」與「菜品」一致?
- 為什麼TDD能讓你的FastAPI開發飛起來? - cmdragon's Blog
- 如何用FastAPI玩轉多模塊測試與異步任務,讓代碼不再“鬧脾氣”? - cmdragon's Blog
- 如何在FastAPI中玩轉“時光倒流”的數據庫事務回滾測試?
- 如何在FastAPI中優雅地模擬多模塊集成測試? - cmdragon's Blog
- 多環境配置切換機制能否讓開發與生產無縫銜接? - cmdragon's Blog
- 如何在 FastAPI 中巧妙覆蓋依賴注入並攔截第三方服務調用? - cmdragon's Blog
- 為什麼你的單元測試需要Mock數據庫才能飛起來? - cmdragon's Blog
- 如何在FastAPI中巧妙隔離依賴項,讓單元測試不再頭疼? - cmdragon's Blog
- 如何在FastAPI中巧妙隔離依賴項,讓單元測試不再頭疼? - cmdragon's Blog
- 測試覆蓋率不夠高?這些技巧讓你的FastAPI測試無懈可擊! - cmdragon's Blog
- 為什麼你的FastAPI測試覆蓋率總是低得讓人想哭? - cmdragon's Blog
- 如何讓FastAPI測試不再成為你的噩夢? - cmdragon's Blog
- FastAPI測試環境配置的秘訣,你真的掌握了嗎? - cmdragon's Blog
- 全鏈路追蹤如何讓FastAPI微服務架構的每個請求都無所遁形? - cmdragon's Blog
- 如何在API高併發中玩轉資源隔離與限流策略? - cmdragon's Blog
- 任務分片執行模式如何讓你的FastAPI性能飆升? - cmdragon's Blog
- 冷熱任務分離:是提升Web性能的終極秘籍還是技術噱頭? - cmdragon's Blog
- 如何讓FastAPI在百萬級任務處理中依然遊刃有餘? - cmdragon's Blog
- 如何讓FastAPI與消息隊列的聯姻既甜蜜又可靠? - cmdragon's Blog
- 如何在FastAPI中巧妙實現延遲隊列,讓任務乖乖等待? - cmdragon's Blog
- FastAPI的死信隊列處理機制:為何你的消息系統需要它? - cmdragon's Blog
- 如何讓FastAPI任務系統在失敗時自動告警並自我修復? - cmdragon's Blog
- 如何用Prometheus和FastAPI打造任務監控的“火眼金睛”? - cmdragon's Blog
- 如何用APScheduler和FastAPI打造永不宕機的分佈式定時任務系統? - cmdragon's Blog
- 如何在 FastAPI 中玩轉 APScheduler,讓任務定時自動執行? - cmdragon's Blog
- 定時任務系統如何讓你的Web應用自動完成那些煩人的重複工作? - cmdragon's Blog
- Celery任務監控的魔法背後藏着什麼秘密? - cmdragon's Blog
- 如何讓Celery任務像VIP客户一樣享受優先待遇? - cmdragon's Blog
- 如何讓你的FastAPI Celery Worker在壓力下優雅起舞? - cmdragon's Blog
- FastAPI與Celery的完美邂逅,如何讓異步任務飛起來? - cmdragon's Blog
- FastAPI消息持久化與ACK機制:如何確保你的任務永不迷路? - cmdragon's Blog
- FastAPI的BackgroundTasks如何玩轉生產者-消費者模式? - cmdragon's Blog
- BackgroundTasks 還是 RabbitMQ?你的異步任務到底該選誰? - cmdragon's Blog
- BackgroundTasks與Celery:誰才是異步任務的終極贏家? - cmdragon's Blog
- 如何在 FastAPI 中優雅處理後台任務異常並實現智能重試? - cmdragon's Blog
</details>
<details>
<summary>免費好用的熱門在線工具</summary>
- 歌詞生成工具 - 應用商店 | By cmdragon
- 網盤資源聚合搜索 - 應用商店 | By cmdragon
- ASCII字符畫生成器 - 應用商店 | By cmdragon
- JSON Web Tokens 工具 - 應用商店 | By cmdragon
- Bcrypt 密碼工具 - 應用商店 | By cmdragon
- GIF 合成器 - 應用商店 | By cmdragon
- GIF 分解器 - 應用商店 | By cmdragon
- 文本隱寫術 - 應用商店 | By cmdragon
- CMDragon 在線工具 - 高級AI工具箱與開發者套件 | 免費好用的在線工具
- 應用商店 - 發現1000+提升效率與開發的AI工具和實用程序 | 免費好用的在線工具
- CMDragon 更新日誌 - 最新更新、功能與改進 | 免費好用的在線工具
- 支持我們 - 成為贊助者 | 免費好用的在線工具
- AI文本生成圖像 - 應用商店 | 免費好用的在線工具
- 臨時郵箱 - 應用商店 | 免費好用的在線工具
- 二維碼解析器 - 應用商店 | 免費好用的在線工具
- 文本轉思維導圖 - 應用商店 | 免費好用的在線工具
- 正則表達式可視化工具 - 應用商店 | 免費好用的在線工具
- 文件隱寫工具 - 應用商店 | 免費好用的在線工具
- IPTV 頻道探索器 - 應用商店 | 免費好用的在線工具
- 快傳 - 應用商店 | 免費好用的在線工具
- 隨機抽獎工具 - 應用商店 | 免費好用的在線工具
- 動漫場景查找器 - 應用商店 | 免費好用的在線工具
- 時間工具箱 - 應用商店 | 免費好用的在線工具
- 網速測試 - 應用商店 | 免費好用的在線工具
- AI 智能摳圖工具 - 應用商店 | 免費好用的在線工具
- 背景替換工具 - 應用商店 | 免費好用的在線工具
- 藝術二維碼生成器 - 應用商店 | 免費好用的在線工具
- Open Graph 元標籤生成器 - 應用商店 | 免費好用的在線工具
- 圖像對比工具 - 應用商店 | 免費好用的在線工具
- 圖片壓縮專業版 - 應用商店 | 免費好用的在線工具
- 密碼生成器 - 應用商店 | 免費好用的在線工具
- SVG優化器 - 應用商店 | 免費好用的在線工具
- 調色板生成器 - 應用商店 | 免費好用的在線工具
- 在線節拍器 - 應用商店 | 免費好用的在線工具
- IP歸屬地查詢 - 應用商店 | 免費好用的在線工具
- CSS網格佈局生成器 - 應用商店 | 免費好用的在線工具
- 郵箱驗證工具 - 應用商店 | 免費好用的在線工具
- 書法練習字帖 - 應用商店 | 免費好用的在線工具
- 金融計算器套件 - 應用商店 | 免費好用的在線工具
- 中國親戚關係計算器 - 應用商店 | 免費好用的在線工具
- Protocol Buffer 工具箱 - 應用商店 | 免費好用的在線工具
- IP歸屬地查詢 - 應用商店 | 免費好用的在線工具
- 圖片無損放大 - 應用商店 | 免費好用的在線工具
- 文本比較工具 - 應用商店 | 免費好用的在線工具
- IP批量查詢工具 - 應用商店 | 免費好用的在線工具
- 域名查詢工具 - 應用商店 | 免費好用的在線工具
- DNS工具箱 - 應用商店 | 免費好用的在線工具
- 網站圖標生成器 - 應用商店 | 免費好用的在線工具
- XML Sitemap
</details>