动态

详情 返回 返回

如何用 GitHub Actions 為 FastAPI 項目打造自動化測試流水線? - 动态 详情


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的模塊搜索路徑未包含項目根目錄。解決方法:

  1. 確保運行pytest時的當前目錄是項目根目錄(如fastapi-ci-demo/);
  2. tests目錄下創建__init__.py,標識tests為Python模塊;
  3. 運行pytest時添加--rootdir參數:pytest --rootdir . tests/

6. 常見報錯與解決方案

在CI流水線運行中,你可能會遇到以下常見錯誤,提前掌握解決方案能節省大量時間。

報錯1:422 Validation Error(測試或API請求中)

  • 原因:請求數據不符合Pydantic模型的驗證規則(如缺少必填字段、類型錯誤);
  • 解決步驟

    1. 查看響應的detail字段(如response.json()["detail"]),找到錯誤位置(loc字段)和原因(msg字段);
    2. 修改請求數據,使其符合模型規則(如補充缺少的email字段);
  • 預防建議:編寫測試用例時覆蓋所有異常場景(如缺少字段、格式錯誤)。

報錯2:pytest找不到測試用例(collected 0 items)

  • 原因:測試文件/函數的命名不符合pytest的默認規則(文件以test_開頭/結尾,函數以test_開頭);
  • 解決步驟

    1. 將測試文件重命名為test_api.py(而非api.py);
    2. 將測試函數重命名為test_create_user(而非create_user);
  • 預防建議:遵循pytest命名規範,避免手動指定測試文件路徑。

報錯3:GitHub Actions中“Install dependencies”失敗

  • 原因

    1. requirements.txt中的版本號錯誤(如fastapi==999.0,不存在的版本);
    2. pip源無法訪問(如默認源被牆);
  • 解決步驟

    1. 驗證依賴版本(通過PyPI查詢最新版);
    2. 更換pip源(如使用阿里雲源):

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

附:CI流水線流程圖

graph TD
    A[Push代碼到main分支] --> B[觸發GitHub Actions工作流]
    B --> C[拉取代碼到Ubuntu虛擬機]
    C --> D[安裝Python 3.11]
    D --> E[安裝FastAPI依賴]
    E --> F[運行pytest測試]
    F --> G[檢查代碼風格(flake8)]
    G --> H{流程成功?}
    H -->|是| I[通知開發者:測試通過]
    H -->|否| J[通知開發者:測試失敗,查看日誌]

通過以上步驟,你已經掌握瞭如何用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>

user avatar kerrycode 头像 banxiazhimo 头像 shoushoudeqie 头像 lengxi_16 头像
点赞 4 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.