欢迎光临
我们一直在努力

AI 全栈开发实战(11):CI/CD 与自动化测试——从 pytest 到 GitHub Actions

AI 项目的 CI/CD 怎么做?自动化测试和部署流水线搭建

代码写完了,怎么保证每次修改不会破坏已有功能?怎么自动部署到服务器?

本篇回答三个问题:

  • 怎么写 AI 项目的自动化测试?
  • CI/CD 流水线怎么配?
  • 部署自动化怎么做?
  • 怎么写 AI 项目的自动化测试?

    后端测试(pytest)

    # backend/tests/test_api.py
    import pytest
    from httpx import ASGITransport, AsyncClient
    from app.main import app

    @pytest.fixture
    def client():
    transport = ASGITransport(app=app)
    return AsyncClient(transport=transport, base_url="http://test")

    @pytest.mark.asyncio
    async def test_health_check(client):
    """健康检查接口测试。"""
    response = await client.get("/api/health")
    assert response.status_code == 200
    assert response.json()["status"] == "ok"

    @pytest.mark.asyncio
    async def test_register(client):
    """用户注册接口测试。"""
    import random
    email = f"test{random.randint(10000,99999)}@example.com"
    response = await client.post("/api/auth/register", json={
    "email": email,
    "password": "test123456",
    "nickname": "测试用户",
    })
    assert response.status_code == 201
    data = response.json()
    assert "access_token" in data
    assert data["user"]["email"] == email

    @pytest.mark.asyncio
    async def test_login_invalid_password(client):
    """错误密码登录测试。"""
    response = await client.post("/api/auth/login", json={
    "email": "nonexist@example.com",
    "password": "wrong",
    })
    assert response.status_code == 401

    @pytest.mark.asyncio
    async def test_create_knowledge_base(client):
    """创建知识库测试(需先登录)。"""
    # 先注册
    import random
    email = f"kb{random.randint(10000,99999)}@example.com"
    reg = await client.post("/api/auth/register", json={
    "email": email, "password": "test123456", "nickname": "test"
    })
    token = reg.json()["access_token"]

    # 创建知识库
    response = await client.post("/api/knowledge-bases",
    json={"name": "测试知识库", "description": "测试描述"},
    headers={"Authorization": f"Bearer {token}"}
    )
    assert response.status_code == 201
    assert response.json()["name"] == "测试知识库"

    测试数据库隔离

    测试不应该用生产数据库。用 pytest 的 fixture 隔离:

    # backend/tests/conftest.py
    import pytest
    from app.database import engine, Base
    from sqlalchemy.ext.asyncio import create_async_engine

    @pytest.fixture(autouse=True)
    async def setup_db():
    """每个测试用例使用独立的数据库会话。"""
    # 使用 SQLite 内存数据库进行测试
    test_engine = create_async_engine("sqlite+aiosqlite:///:memory:")
    async with test_engine.begin() as conn:
    await conn.run_sync(Base.metadata.create_all)
    yield
    await test_engine.dispose()

    CI/CD 流水线怎么配?

    GitHub Actions 配置

    # .github/workflows/ci.yml
    name: CI

    on:
    push:
    branches: [main, develop]
    pull_request:
    branches: [main]

    jobs:
    test:
    runs-on: ubuntu–latest

    services:
    postgres:
    image: postgres:16–alpine
    env:
    POSTGRES_DB: know_test
    POSTGRES_USER: know
    POSTGRES_PASSWORD: know_test
    ports:
    – 5432:5432
    options: ––health–cmd pg_isready ––health–interval 10s ––health–timeout 5s ––health–retries 5

    redis:
    image: redis:7–alpine
    ports:
    – 6379:6379
    options: ––health–cmd "redis–cli ping" ––health–interval 10s ––health–timeout 5s ––health–retries 5

    steps:
    – uses: actions/checkout@v4

    – name: Set up Python
    uses: actions/setup–python@v5
    with:
    python-version: "3.11"

    – name: Install dependencies
    run: |
    cd backend
    pip install -r requirements.txt
    pip install pytest httpx pytest-asyncio

    – name: Run tests
    env:
    DATABASE_URL: postgresql+asyncpg://know:know_test@localhost:5432/know_test
    REDIS_URL: redis://localhost:6379/0
    run: |
    cd backend
    pytest tests/ -v –cov=app –cov-report=term-missing

    代码质量检查

    # 在 ci.yml 中加一个 lint job
    lint:
    runs-on: ubuntu–latest
    steps:
    – uses: actions/checkout@v4
    – uses: actions/setup–python@v5
    with:
    python-version: "3.11"
    – run: pip install ruff mypy
    – run: ruff check backend/
    – run: mypy backend/ ––ignore–missing–imports

    Docker 镜像构建与推送

    build:
    needs: [test, lint]
    runs-on: ubuntu–latest
    if: github.ref == 'refs/heads/main'
    steps:
    – uses: actions/checkout@v4

    – name: Set up Docker Buildx
    uses: docker/setup–buildx–action@v3

    – name: Log in to Docker Hub
    uses: docker/login–action@v3
    with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}

    – name: Build and push backend
    uses: docker/build–push–action@v5
    with:
    context: ./backend
    push: true
    tags: yourdockerhub/know–backend:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

    – name: Build and push frontend
    uses: docker/build–push–action@v5
    with:
    context: ./frontend
    push: true
    tags: yourdockerhub/know–frontend:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

    部署自动化怎么做?

    自动部署到服务器

    deploy:
    needs: [build]
    runs-on: ubuntu–latest
    if: github.ref == 'refs/heads/main'
    steps:
    – name: Deploy via SSH
    uses: appleboy/ssh–action@v1.0.3
    with:
    host: ${{ secrets.DEPLOY_HOST }}
    username: ${{ secrets.DEPLOY_USER }}
    key: ${{ secrets.DEPLOY_KEY }}
    script: |
    cd /opt/know
    docker compose pull
    docker compose up -d –force-recreate
    docker image prune -f

    完整 CI/CD 流水线

    提交代码 → 自动测试 → 代码检查 → 构建镜像 → 推送到仓库 → 自动部署
    git push pytest ruff docker docker push ssh deploy

    本地测试常用命令

    # 运行所有测试
    cd backend && pytest tests/ -v

    # 运行单个测试文件
    pytest tests/test_api.py -v

    # 运行单个测试函数
    pytest tests/test_api.py::test_register -v

    # 带覆盖率报告
    pytest tests/ –cov=app –cov-report=html

    # 代码格式检查
    ruff check app/

    # 类型检查
    mypy app/

    总结

    环节工具作用
    单元测试 pytest + httpx 保证接口正确性
    代码质量 ruff + mypy 保证代码规范
    CI GitHub Actions 自动运行测试和检查
    CD Docker + SSH 自动构建和部署

    本文是 《AI 全栈开发实战——做一个真正的产品》 系列的第 11 篇。 本文由 Zyentor(智元界) 原创发布


    本文发布于 Zyentor(智元界) —— AI 开发者社区 原文链接:https://www.zyentor.com/news/3881

    赞(0)
    未经允许不得转载:171主机测评 » AI 全栈开发实战(11):CI/CD 与自动化测试——从 pytest 到 GitHub Actions
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址