DeerFlow自动化测试:基于Python的CI/CD集成方案
DeerFlow自动化测试:基于Python的CI/CD集成方案
如果你正在用DeerFlow做深度研究,每次手动运行测试、检查代码质量,是不是觉得有点麻烦?特别是当项目更新频繁,或者团队协作开发时,手动测试不仅效率低,还容易出错。
今天我就来分享一个实用的方案:把DeerFlow的自动化测试集成到Python项目的CI/CD流程里。简单说,就是让代码每次提交都能自动跑测试、生成报告,你只需要关注结果就行。这套方案基于GitHub Actions,配置简单,效果明显,能帮你节省大量时间。
1. 为什么需要CI/CD集成?
先说说我自己的经历。刚开始用DeerFlow时,每次改完代码都要手动跑一遍测试,看看有没有问题。时间一长就发现几个痛点:
手动测试的麻烦
- 容易忘记跑测试,导致问题没及时发现
- 测试结果分散,没有统一记录
- 团队协作时,每个人的环境配置不同,测试结果可能不一致
- 代码质量检查靠自觉,标准不统一
CI/CD能解决什么
- 代码一提交就自动跑测试,不用手动操作
- 测试结果集中管理,随时查看历史记录
- 确保所有人在同一标准下开发
- 自动生成测试报告,问题一目了然
DeerFlow本身就有完善的测试框架,支持单元测试、集成测试和覆盖率检查。我们要做的就是把这套测试流程自动化,让它成为开发流程的一部分。
2. 环境准备与基础配置
在开始配置CI/CD之前,先确保你的DeerFlow项目已经设置好本地测试环境。如果你还没做过,跟着下面几步快速过一遍。
2.1 检查现有测试框架
DeerFlow项目已经内置了测试框架,用make命令就能管理。打开项目根目录,看看有没有这些文件:
# 查看测试相关文件
ls -la tests/
ls -la Makefile
你应该能看到类似这样的结构:
tests/
├── integration/
│ └── test_workflow.py
├── unit/
│ └── test_*.py
└── conftest.py
Makefile # 包含test、coverage等命令
2.2 本地测试验证
先确保本地测试能正常运行,这样CI/CD配置才有意义:
# 安装测试依赖(如果还没装)
uv pip install -e ".[test]"
# 运行所有测试
make test
# 运行特定集成测试
pytest tests/integration/test_workflow.py -v
# 检查测试覆盖率
make coverage
如果这些命令都能正常执行,说明测试环境没问题。记下测试用时和覆盖率结果,后面配置CI时会用到。
2.3 准备必要的配置文件
DeerFlow测试需要一些环境配置,主要是API密钥和模型设置。为了在CI环境中安全使用,我们需要处理敏感信息:
# 复制示例配置文件
cp .env.example .env.ci
cp conf.yaml.example conf.yaml.ci
# 编辑.ci文件,使用测试专用的占位符
# 在.env.ci中:
SEARCH_API=duckduckgo # 使用无需API的搜索引擎
# 其他API密钥留空或使用测试专用密钥
# 在conf.yaml.ci中:
# 使用本地测试模型或模拟接口
重要提示:实际项目中,API密钥等敏感信息应该使用GitHub Secrets管理,不要直接写在配置文件里。我们后面会详细讲怎么安全配置。
3. GitHub Actions工作流配置
现在进入核心部分:配置GitHub Actions。我会分步骤讲解,每个配置都有详细说明。
3.1 基础工作流文件
在项目根目录创建.github/workflows/test.yml文件:
name: DeerFlow CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
# 每周一早上6点运行一次完整测试
- cron: '0 6 * * 1'
env:
PYTHON_VERSION: '3.12'
UV_VERSION: '0.4.0'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv sync --all-extras
uv pip install -e ".[test]"
- name: Run tests
run: make test
- name: Generate coverage report
run: make coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
这个基础配置做了几件事:
- 在代码推送或PR时自动触发
- 设置Python 3.12环境(DeerFlow要求)
- 安装uv包管理器
- 安装项目依赖和测试依赖
- 运行测试并生成覆盖率报告
- 上传报告到Codecov(可选)
3.2 处理环境变量和敏感信息
测试DeerFlow需要API密钥,但在CI环境中不能明文存储。用GitHub Secrets安全管理:
# 在test job的steps中添加
- name: Setup environment variables
env:
TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# 其他需要的API密钥
run: |
# 创建测试用的.env文件
cat > .env << EOF
SEARCH_API=tavily
TAVILY_API_KEY=${TAVILY_API_KEY:-}
LANGSMITH_TRACING=false
EOF
# 创建测试用的conf.yaml
cat > conf.yaml << EOF
BASIC_MODEL:
base_url: "https://api.openai.com/v1"
model: "gpt-3.5-turbo"
api_key: ${OPENAI_API_KEY:-}
EOF
然后在GitHub仓库设置中添加Secrets:
- 进入仓库 → Settings → Secrets and variables → Actions
- 点击"New repository secret"
- 添加TAVILY_API_KEY、OPENAI_API_KEY等
- 值填实际的API密钥(测试环境可以用限制权限的密钥)
3.3 矩阵测试配置
为了确保兼容性,可以测试多个Python版本:
jobs:
test:
strategy:
matrix:
python-version: ['3.12', '3.13']
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
# ... 前面的步骤相同
- name: Run tests with matrix
run: |
# 根据OS调整命令
if [ "$RUNNER_OS" == "Windows" ]; then
# Windows特定命令
python -m pytest tests/ -v
else
make test
fi
3.4 集成测试专项配置
DeerFlow的集成测试可能需要更多资源,可以单独配置:
integration-test:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up environment
run: |
# 安装Docker(如果需要)
sudo apt-get update
sudo apt-get install -y docker.io
- name: Run integration tests
timeout-minutes: 30
run: |
# 启动测试需要的服务
docker-compose -f docker-compose.test.yml up -d
# 等待服务就绪
sleep 30
# 运行集成测试
pytest tests/integration/ -v --tb=short
# 清理
docker-compose -f docker-compose.test.yml down
4. 测试用例编写与优化
CI/CD的核心是测试用例的质量。DeerFlow的测试主要分三类,每类都有不同的编写策略。
4.1 单元测试:验证核心组件
单元测试关注单个函数或类的行为。DeerFlow的agent节点、工具函数都适合做单元测试:
# tests/unit/test_coordinator.py
import pytest
from deerflow.src.graph.nodes import coordinator_node
from deerflow.src.graph.state import State
def test_coordinator_with_valid_input():
"""测试coordinator处理正常输入"""
state = State(
messages=[{"role": "user", "content": "什么是机器学习?"}],
locale="zh"
)
result = coordinator_node(state)
assert result is not None
assert "goto" in result
# coordinator应该将控制权交给planner
assert result["goto"] == "planner"
def test_coordinator_with_sensitive_content():
"""测试coordinator处理敏感内容"""
state = State(
messages=[{"role": "user", "content": "敏感测试内容"}],
locale="zh"
)
result = coordinator_node(state)
# 应该礼貌拒绝并结束
assert result["goto"] == "__end__"
assert "抱歉" in str(result.get("update", {}))
def test_coordinator_edge_cases():
"""测试边界情况"""
# 空消息
state = State(messages=[], locale="zh")
result = coordinator_node(state)
assert result["goto"] == "__end__"
# 超长消息
long_content = "test" * 1000
state = State(messages=[{"role": "user", "content": long_content}], locale="zh")
result = coordinator_node(state)
# 应该能正常处理或截断
assert result is not None
4.2 集成测试:验证工作流
集成测试关注多个组件如何协作。DeerFlow的多agent工作流特别适合集成测试:
# tests/integration/test_workflow.py
import pytest
from deerflow.src.graph.graph import create_workflow_graph
from langgraph.checkpoint.memory import MemorySaver
class TestDeerFlowWorkflow:
@pytest.fixture
def workflow(self):
"""创建测试用的工作流图"""
memory = MemorySaver()
graph = create_workflow_graph(checkpointer=memory)
return graph
def test_basic_research_flow(self, workflow):
"""测试基础研究流程"""
config = {"configurable": {"thread_id": "test_thread_1"}}
# 初始化状态
inputs = {
"messages": [{"role": "user", "content": "Python是什么?"}],
"locale": "zh"
}
# 执行工作流
for event in workflow.stream(inputs, config):
# 检查每个步骤的状态
if "coordinator" in event:
assert event["coordinator"] is not None
elif "planner" in event:
# planner应该生成研究计划
plan = event["planner"].get("current_plan")
assert plan is not None
assert hasattr(plan, "steps")
# 最终应该生成报告
final_state = workflow.get_state(config)
assert "final_report" in final_state.values
def test_workflow_with_human_feedback(self, workflow):
"""测试带人工反馈的流程"""
config = {"configurable": {"thread_id": "test_thread_2"}}
inputs = {
"messages": [{"role": "user", "content": "解释深度学习"}],
"locale": "zh",
"auto_accepted_plan": False # 启用人工反馈
}
# 模拟人工反馈
events = []
for event in workflow.stream(inputs, config):
events.append(event)
# 当进入human_feedback节点时,模拟用户输入
if "human_feedback" in event:
feedback_event = workflow.invoke(
{"feedback": "[ACCEPTED]"},
config
)
events.append(feedback_event)
# 验证流程完成
assert len(events) > 0
assert any("reporter" in str(e) for e in events)
4.3 模拟外部依赖
测试时不应该调用真实API,既慢又不稳定。用pytest-mock模拟外部服务:
# tests/unit/test_researcher.py
import pytest
from unittest.mock import Mock, AsyncMock
from deerflow.src.graph.nodes import researcher_node
from deerflow.src.tools.search import TavilySearchTool
@pytest.mark.asyncio
async def test_researcher_with_mocked_search(mocker):
"""测试researcher使用模拟的搜索工具"""
# 模拟Tavily搜索返回
mock_search = mocker.patch.object(TavilySearchTool, '_arun')
mock_search.return_value = [
{
"title": "测试结果",
"content": "这是模拟的搜索结果",
"url": "https://example.com"
}
]
# 创建测试状态
state = {
"current_plan": Mock(
steps=[Mock(
step_type="RESEARCH",
description="搜索Python相关信息",
execution_res=None
)]
),
"observations": []
}
result = await researcher_node(state)
# 验证搜索被调用
mock_search.assert_called_once()
# 验证结果处理
assert "observations" in result.get("update", {})
observations = result["update"]["observations"]
assert len(observations) > 0
assert "测试结果" in str(observations)
def test_researcher_error_handling(mocker):
"""测试researcher的错误处理"""
# 模拟搜索失败
mocker.patch.object(TavilySearchTool, '_arun',
side_effect=Exception("API错误"))
state = {
"current_plan": Mock(
steps=[Mock(step_type="RESEARCH", description="测试搜索")]
),
"observations": []
}
# 应该能处理异常而不崩溃
try:
result = researcher_node(state)
# 如果有结果,应该包含错误信息
if result:
assert "error" in str(result).lower()
except Exception:
pytest.fail("researcher应该处理API错误,而不是抛出异常")
5. 测试报告与质量门禁
测试不仅要运行,还要有清晰的报告和质量标准。这样才能真正提升代码质量。
5.1 生成详细的测试报告
在GitHub Actions中配置测试报告生成:
- name: Run tests with detailed reporting
run: |
# 生成JUnit格式报告(供GitHub显示)
pytest tests/ \
--junitxml=test-results.xml \
--cov=deerflow \
--cov-report=xml:coverage.xml \
--cov-report=html:coverage_html \
-v
# 生成测试时长报告
pytest tests/ --durations=10 > test-durations.txt
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: test-reports
path: |
test-results.xml
coverage.xml
coverage_html/
test-durations.txt
retention-days: 30
- name: Publish Test Report
uses: dorny/test-reporter@v1
if: always() # 即使测试失败也生成报告
with:
name: Pytest Results
path: test-results.xml
reporter: java-junit
5.2 设置质量门禁
定义测试通过的标准,不达标就阻止合并:
quality-gate:
needs: test
runs-on: ubuntu-latest
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: test-reports
- name: Check test results
run: |
# 检查测试是否全部通过
if grep -q 'failures="[1-9]' test-results.xml; then
echo " 有测试失败,请检查"
exit 1
fi
# 检查覆盖率是否达标
MIN_COVERAGE=80
COVERAGE=$(grep -o 'line-rate="[0-9.]*"' coverage.xml | grep -o '[0-9.]*' | head -1)
COVERAGE_PERCENT=$(echo "$COVERAGE * 100" | bc)
if (( $(echo "$COVERAGE_PERCENT < $MIN_COVERAGE" | bc -l) )); then
echo " 代码覆盖率 ${COVERAGE_PERCENT}% 低于要求 ${MIN_COVERAGE}%"
exit 1
else
echo " 代码覆盖率 ${COVERAGE_PERCENT}% 达标"
fi
# 检查测试时长(防止测试过慢)
MAX_DURATION=300 # 5分钟
TOTAL_TIME=$(grep -o 'time="[0-9.]*"' test-results.xml | grep -o '[0-9.]*' | awk '{sum+=$1} END {print sum}')
if (( $(echo "$TOTAL_TIME > $MAX_DURATION" | bc -l) )); then
echo " 测试总时长 ${TOTAL_TIME}s 超过 ${MAX_DURATION}s,考虑优化"
# 这里不失败,只是警告
fi
5.3 代码质量检查
除了测试,还要检查代码风格和类型:
lint-and-type-check:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
uv sync
uv pip install black ruff mypy types-requests
- name: Check code formatting with Black
run: |
black --check --diff deerflow/ tests/
- name: Lint with Ruff
run: |
ruff check deerflow/ tests/ --fix
- name: Type checking with MyPy
run: |
mypy deerflow/ --ignore-missing-imports
- name: Security check with Bandit
run: |
uv pip install bandit
bandit -r deerflow/ -ll
6. 高级配置与优化技巧
基础配置完成后,可以进一步优化CI/CD流程,提升效率和稳定性。
6.1 缓存依赖加速构建
GitHub Actions可以缓存Python依赖,大幅减少构建时间:
- name: Cache uv dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/uv
.venv
key: ${{ runner.os }}-uv-${{ hashFiles('pyproject.toml', 'uv.lock') }}
restore-keys: |
${{ runner.os }}-uv-
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements*.txt') }}
6.2 并行测试执行
对于大型测试套件,可以并行运行测试加快速度:
- name: Run tests in parallel
run: |
# 使用pytest-xdist并行运行
pytest tests/ -n auto --dist=loadscope
# 或者按目录拆分
pytest tests/unit/ -n 2 &
pytest tests/integration/ -n 2 &
wait
6.3 数据库和外部服务测试
DeerFlow可能用到数据库(如PostgreSQL checkpoint),需要测试环境:
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: testpassword
POSTGRES_DB: testdb
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
- name: Test with PostgreSQL
env:
DATABASE_URL: postgresql://postgres:testpassword@localhost:5432/testdb
run: |
# 设置环境变量
export LANGGRAPH_CHECKPOINT_SAVER=true
export LANGGRAPH_CHECKPOINT_DB_URL=$DATABASE_URL
# 运行数据库相关测试
pytest tests/integration/test_checkpoint.py -v
6.4 性能测试集成
对于DeerFlow这样的AI应用,性能也很重要:
performance-test:
runs-on: ubuntu-latest
needs: test
steps:
- name: Run performance tests
timeout-minutes: 10
run: |
# 安装性能测试工具
uv pip install pytest-benchmark
# 运行基准测试
pytest tests/performance/ -v --benchmark-only
# 检查响应时间
python -c "
import time
from deerflow.src.graph.graph import create_workflow_graph
graph = create_workflow_graph()
start = time.time()
# 测试典型查询
inputs = {'messages': [{'role': 'user', 'content': '简单测试'}]}
for _ in graph.stream(inputs, {'configurable': {'thread_id': 'perf_test'}}):
pass
duration = time.time() - start
print(f'工作流执行时间: {duration:.2f}秒')
assert duration < 30, '响应时间过长'
"
7. 实际应用与问题排查
配置完成后,在实际使用中可能会遇到一些问题。这里分享一些常见问题的解决方法。
7.1 常见问题与解决
问题1:测试在CI中通过,但本地失败
# 解决方案:确保环境一致
- name: Use consistent Python version
uses: actions/setup-python@v5
with:
python-version: '3.12.8' # 指定精确版本
问题2:API密钥在CI中失效
# 解决方案:使用测试专用密钥和模拟
- name: Use mock for external APIs in CI
env:
USE_MOCK_APIS: 'true'
run: |
if [ "$USE_MOCK_APIS" = "true" ]; then
# 使用模拟服务
export SEARCH_API=duckduckgo # 无需密钥
# 或者启动本地模拟服务器
python -m tests.mock_services &
fi
问题3:测试超时
# 解决方案:设置超时和重试
- name: Run tests with timeout and retry
timeout-minutes: 15
continue-on-error: true # 超时不立即失败
- name: Retry flaky tests
if: failure()
run: |
# 只重试失败的测试
pytest tests/ --lf -v
7.2 监控与告警
配置测试失败时的通知:
- name: Notify on failure
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `CI/CD Test Failed on ${context.ref}`,
body: `测试运行失败,请检查:\n\n${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
labels: ['ci-failure']
})
7.3 定期维护任务
设置定期任务维护测试健康度:
name: Weekly Test Maintenance
on:
schedule:
- cron: '0 2 * * 0' # 每周日早上2点
jobs:
update-dependencies:
runs-on: ubuntu-latest
steps:
- name: Update dependencies
run: |
uv lock --upgrade
# 运行测试确保兼容性
make test
- name: Create PR if updates available
uses: peter-evans/create-pull-request@v5
with:
commit-message: 'chore: update dependencies'
title: 'Weekly dependency updates'
body: '自动更新的依赖包'
branch: 'deps-update'
8. 总结
把DeerFlow集成到CI/CD流程里,看起来要配置不少东西,但实际用起来真的很省心。我自己的项目配置完后,最大的感受就是放心——代码质量有保障,问题能早发现,团队协作也更顺畅。
这套方案的核心思路其实很简单:自动化能手动做的事,标准化能自动化的流程。从基础测试到质量门禁,每一步都是为了减少人为错误,提升开发效率。
如果你刚开始接触CI/CD,建议先从基础测试开始,跑通整个流程后再慢慢添加高级功能。遇到问题也不用担心,GitHub Actions的日志很详细,大部分问题都能找到解决方法。
实际用下来,这套配置在中等规模的项目里效果不错,测试运行稳定,反馈及时。当然,每个项目情况不同,你可能需要根据实际需求调整一些参数,比如测试覆盖率要求、超时时间等。关键是要找到适合自己团队的平衡点,既保证质量,又不拖慢开发节奏。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐



所有评论(0)