You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置GitHub Actions实现pytest仅运行PR变更相关测试

配置方案

核心实现逻辑:

  • 修正代码检出步骤的浅克隆限制,拉取完整提交历史用于分支diff对比
  • 在测试执行前新增文件收集步骤,通过git diff拿到当前PR相对于master分支的所有变更文件
  • 按照目录映射规则匹配变更文件对应的pytest测试用例,仅将匹配到的测试路径传入pytest执行

完整修改后的工作流配置

name: Python tests

on:
  pull_request:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          # 拉取完整提交历史,支持分支diff对比
          fetch-depth: 0

      - name: Set up Python
        uses: actions/setup-python@v3
        with:
          python-version: "3.10"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flake8 pytest
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

      - name: Lint with flake8
        run: |
          # 存在Python语法错误或未定义名称时直接终止构建
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          # 其余风格问题仅做警告提示
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

      - name: Collect changed files and match test cases
        id: collect-tests
        run: |
          # 获取PR相对于master分支的所有变更Python文件
          CHANGED_FILES=$(git diff --name-only origin/master...HEAD -- "*.py")
          TEST_FILES=()

          for file in $CHANGED_FILES; do
            # 规则1:变更的是tests目录下的测试文件,直接加入执行列表
            if [[ $file == tests/test_*.py ]]; then
              if [ -f "$file" ]; then
                TEST_FILES+=("$file")
              fi
            fi

            # 规则2:变更的是utils目录下的源码文件,映射对应test文件
            if [[ $file == utils/*.py ]]; then
              # 提取源码文件名,拼接对应测试文件路径
              src_filename=$(basename "$file" .py)
              test_path="tests/test_${src_filename}.py"
              if [ -f "$test_path" ]; then
                TEST_FILES+=("$test_path")
              fi
            fi

            # 可选规则:如果改了公共配置、根目录初始化文件,直接跑全量测试
            if [[ $file == utils/__init__.py || $file == requirements.txt ]]; then
              TEST_FILES=("tests/")
              break
            fi
          done

          # 去重测试文件列表
          UNIQUE_TESTS=($(echo "${TEST_FILES[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
          
          # 输出结果,供后续步骤使用
          if [ ${#UNIQUE_TESTS[@]} -eq 0 ]; then
            echo "test_files=" >> $GITHUB_OUTPUT
            echo "::notice::No matched test cases for changed files, skip pytest."
          else
            echo "Matched test cases to run: ${UNIQUE_TESTS[*]}"
            echo "test_files=${UNIQUE_TESTS[*]}" >> $GITHUB_OUTPUT
          fi

      - name: Test with pytest
        if: steps.collect-tests.outputs.test_files != ''
        run: |
          pytest ${{ steps.collect-tests.outputs.test_files }}

规则说明

  • 配置完全适配你当前的仓库目录结构:utils/存源码、tests/存测试,测试文件命名为test_<对应源码文件名>.py
  • 以你给出的场景为例:PR仅新增utils/sub.py和tests/test_sub.py时,diff识别到变更后只会匹配tests/test_sub.py传入pytest,原有test_add.py不会被执行
  • 如果改动了公共初始化文件utils/__init__.py或依赖文件requirements.txt,会自动触发全量测试,避免漏测公共逻辑变更
  • 没有匹配到任何对应测试用例时,会自动跳过pytest步骤并给出提示,不会导致CI报错

内容的提问来源于stack exchange,提问作者Shivam Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 19:24:24