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

如何通过GitHub Actions将PR中的Python文件传入pytest执行测试

解决GitHub Action中仅测试PR变更Python文件的问题

问题场景

在GitHub Action中,想要仅对PR里变更的Python文件执行pytest测试,而非全目录运行。当前Action脚本通过tj-actions/changed-files获取变更文件,循环执行pytest时出现如下错误:

Testing Lessons/Intro-to-Python/1/Activities/01-Ins_Python_Intro/Solved/variables_solution.py
======================== test session starts =========================
platform linux -- Python 3.10.13, pytest-8.0.1, pluggy-1.4.0
rootdir: /home/runner/work/GitHub-Actions-Playground/GitHub-Actions-Playground
collected 0 items
===================== no tests ran in 0.01s =======================
Error: Process completed with exit code 5.

核心原因

  1. 退出码5的含义:pytest的退出码5表示未找到任何可执行的测试用例。你执行的variables_solution.py是业务代码文件,本身不包含pytest可识别的测试用例(pytest默认识别test_*.py或*_test.py命名的文件,以及文件内test_开头的函数/类)。
  2. 循环执行的缺陷:当前脚本对每个变更的Python文件单独执行pytest,只要有一个文件无测试用例,就会直接触发错误终止整个Action,后续文件无法执行。
  3. 文件名处理风险:直接用for file in ${{ steps.changed-files.outputs.all_changed_files }}遍历,会把带空格的文件名拆分成多个元素,导致路径错误。

解决方案

方案1:仅测试变更的测试文件

如果目标是跑PR中修改的测试文件,可直接筛选符合pytest命名规则的文件,批量执行:

修改Action的changed-files步骤和测试步骤:

jobs:
  build:
    name: Testing Python Files
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: read
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get changed test Python files
        id: changed-test-files
        uses: tj-actions/changed-files@v42
        with:
          since_last_remote_commit: true
          # 只筛选符合pytest命名规则的测试文件
          files: |
            **/test_*.py
            **/*_test.py

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

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest

      - name: Run pytest on changed test files
        run: |
          CHANGED_TESTS="${{ steps.changed-test-files.outputs.all_changed_files }}"
          if [ -z "$CHANGED_TESTS" ]; then
            echo "No changed test files to run."
            exit 0
          fi
          # 处理带空格的文件名,转成数组
          readarray -t TEST_FILES <<< "$CHANGED_TESTS"
          pytest "${TEST_FILES[@]}"

方案2:针对变更的业务文件,关联执行对应的测试文件

如果要测试变更业务代码对应的测试用例(比如业务文件variables_solution.py对应测试文件test_variables_solution.py),可以通过文件名关联找到测试文件再执行:

修改测试步骤:

- name: Testing Python files
        run: |
          # 获取所有变更的Python文件
          CHANGED_PY_FILES="${{ steps.changed-files.outputs.all_changed_files }}"
          if [ -z "$CHANGED_PY_FILES" ]; then
            echo "No changed Python files to test."
            exit 0
          fi
          readarray -t PY_FILES <<< "$CHANGED_PY_FILES"
          
          TEST_FILES=()
          for file in "${PY_FILES[@]}"; do
            # 跳过本身就是测试文件的情况(如果需要的话)
            if [[ $file == test_*.py || $file == *_test.py ]]; then
              TEST_FILES+=("$file")
              continue
            fi
            # 生成对应的测试文件名(假设测试文件命名为test_xxx.py)
            TEST_FILE=$(echo "$file" | sed 's/\(.*\)\.py/test_\1.py/')
            # 如果测试文件存在,加入列表
            if [ -f "$TEST_FILE" ]; then
              TEST_FILES+=("$TEST_FILE")
            fi
          done

          if [ ${#TEST_FILES[@]} -eq 0 ]; then
            echo "No related test files found for changed Python files."
            exit 0
          fi
          
          echo "Running tests for: ${TEST_FILES[*]}"
          pytest "${TEST_FILES[@]}"

方案3:允许无测试用例的文件,避免Action失败

如果希望即使变更文件无测试用例,Action也不失败,可以给单个pytest命令添加容错处理(不推荐,可能掩盖真实测试错误):

for file in "${PY_FILES[@]}"; do
  if [[ $file == *.py ]]; then
    echo "Testing $file"
    # 仅忽略无测试用例的错误,其他错误正常抛出
    pytest $file || if [ $? -eq 5 ]; then echo "No tests found in $file"; else exit 1; fi
  fi
done

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 04:53:20