برای راه اندازی GitHub Actions برای پایتون که در هر Push و Pull Request تست‌ها را اجرا کند، یک فایل workflow در مسیر .github/workflows/python-tests.yml بسازید، نسخه‌های پایتون موردنظر را با matrix تعیین کنید، وابستگی‌ها را نصب کنید و pytest را اجرا کنید. در ادامه یک فایل نمونه کامل همراه با کش pip، گزارش پوشش کد و چند نکته عملی آماده استفاده می‌بینید.

پیش نیازهای کوتاه

  • مخزن شما روی GitHub قرار داشته باشد.
  • تست‌ها با pytest یا ابزار مشابه آماده باشند (مثلا پوشه tests/ و فایل‌های test_*.py).
  • لیست وابستگی‌ها در requirements.txt یا پیکربندی pyproject.toml مشخص باشد.
  • نسخه‌های هدف پایتون را بشناسید (مثلا 3.9 تا 3.12).

کمترین پیکربندی قابل اتکا (pytest + requirements.txt)

این فایل روی هر Push و Pull Request اجرا می‌شود، وابستگی‌ها را نصب می‌کند، کش pip را فعال می‌کند و pytest را اجرا می‌کند.

name: Python tests

on:
  push:
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  tests:
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: "pip"
          cache-dependency-path: |
            requirements.txt
            requirements-dev.txt

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements-dev.txt ]; then
            python -m pip install -r requirements-dev.txt
          elif [ -f requirements.txt ]; then
            python -m pip install -r requirements.txt
          else
            echo "No requirements file found"
          fi

      - name: Run tests
        run: pytest -q

نتیجه موفق یعنی تمام تست‌ها پاس شده‌اند و خروجی job سبز است. اگر هر تستی fail شود، job قرمز می‌شود و می‌توانید لاگ‌ها را در همان مرحله Run tests بررسی کنید.

پوشش کد و ذخیره گزارش‌ها (Artifacts)

برای اندازه گیری پوشش کد و نگه داشتن گزارش‌ها به عنوان artifact مراحل زیر را به workflow اضافه کنید:

      - name: Install test tools
        run: |
          python -m pip install pytest pytest-cov

      - name: Run tests with coverage
        run: pytest -q --cov=YOUR_PACKAGE --cov-report=xml

      - name: Upload coverage report
        uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.python-version }}
          path: coverage.xml

به جای YOUR_PACKAGE نام پکیج/ماژول اصلی خود را بگذارید. فایل coverage.xml در تب Artifacts هر اجرای workflow قابل دانلود است. اگر قصد ارسال پوشش به سرویس‌های خارجی دارید، دستورالعمل رسمی همان سرویس را دنبال کنید.

افزایش سرعت و پایداری اجرای CI

  • کش pip: با پارامتر cache: “pip” و cache-dependency-path سرعت نصب وابستگی‌ها بسیار بهتر می‌شود.
  • لغو اجرای موازی تکراری: بخش concurrency باعث می‌شود اگر چندین Push روی یک شاخه پشت سر هم بیاید، اجرای قبلی لغو شود.
  • fail-fast: اگر می‌خواهید در matrix با اولین خطا کل job متوقف شود، مقدار آن را true کنید. برای دیدن خطای هر نسخه بهتر است false بماند.
  • Timeout: برای جلوگیری از اجرای طولانی غیرعادی، می‌توانید به job تایم اوت بدهید:
        timeout-minutes: 15
    

تهیه تنظیمات دقیق تری برای اجرا

فیلتر کردن تغییرات غیرمرتبط

اگر می‌خواهید اجرای CI برای تغییرات صرفا مستندات یا Markdown انجام نشود:

on:
  push:
    paths-ignore:
      - 'docs/**'
      - '**/*.md'
  pull_request:
    paths-ignore:
      - 'docs/**'
      - '**/*.md'

نیاز به متغیرهای محیطی و Secretها در تست

اگر تست‌ها به کلیدها یا آدرس‌های خصوصی نیاز دارند، آن‌ها را به صورت Secret در تنظیمات مخزن ذخیره کنید و در env استفاده کنید:

      - name: Run tests with env
        env:
          API_BASE_URL: https://api.example.com
          API_TOKEN: ${{ secrets.API_TOKEN }}
        run: pytest -q

هیچ گاه مقادیر حساس را در مخزن قرار ندهید.

گزینه های رایج دیگر: Poetry و tox

Poetry

اگر از Poetry استفاده می‌کنید، نصب و اجرای تست می‌تواند چنین باشد:

      - name: Install Poetry
        run: |
          python -m pip install --upgrade pip
          python -m pip install poetry

      - name: Install deps (Poetry)
        run: poetry install --no-interaction --no-ansi

      - name: Run tests (Poetry)
        run: poetry run pytest -q

tox

برای مدیریت ماتریس نسخه‌ها و محیط‌ها با tox (و فایل tox.ini):

      - name: Install tox
        run: |
          python -m pip install --upgrade pip
          python -m pip install tox

      - name: Run tox
        run: tox -q

در این حالت تعریف نسخه‌ها و دستورات نصب/اجرا داخل tox.ini مدیریت می‌شود و workflow شما ساده‌تر خواهد بود.

بررسی نتیجه و خطاهای رایج

  • ModuleNotFoundError یا ImportError: ساختار پکیج یا مسیر نصب درست نیست. مطمئن شوید پوشه پروژه فایل __init__.py دارد و نصب وابستگی‌ها موفق بوده است.
  • عدم کش شدن وابستگی‌ها: مسیر cache-dependency-path باید به فایل‌های واقعی وابستگی اشاره کند. نام فایل را درست بنویسید.
  • تست‌ها محلی پاس می‌شوند ولی روی CI نه: نسخه پایتون یا سیستم عامل متفاوت است. از matrix نسخه‌ها استفاده کنید و وابستگی‌های سیستم‌عاملی احتمالی را به صورت build-essentials نصب کنید.
  • وابستگی‌های اضافی dev: اگر pytest در requirements-dev.txt است، مطمئن شوید مرحله نصب dev اجرا می‌شود.
  • تست‌های وابسته به شبکه: اگر تست‌ها به سرویس‌های بیرونی وصل می‌شوند، آن‌ها را mock کنید تا CI پایدار و سریع بماند.

یک نمونه کامل‌تر: تست، پوشش، آرتیفکت و فیلتر تغییرات

این نمونه، اکثر الگوهای عملی را یکجا نشان می‌دهد.

name: Python tests

on:
  push:
    paths-ignore:
      - 'docs/**'
      - '**/*.md'
  pull_request:
    paths-ignore:
      - 'docs/**'
      - '**/*.md'

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  tests:
    runs-on: ubuntu-latest
    timeout-minutes: 20

    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: "pip"
          cache-dependency-path: |
            requirements*.txt
            pyproject.toml
            poetry.lock

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements-dev.txt ]; then
            python -m pip install -r requirements-dev.txt
          elif [ -f requirements.txt ]; then
            python -m pip install -r requirements.txt
          else
            echo "Falling back to minimal test deps"
            python -m pip install pytest pytest-cov
          fi

      - name: Run tests with coverage
        env:
          # نمونه: اگر لازم دارید
          # API_TOKEN: ${{ secrets.API_TOKEN }}
          # APP_ENV: ci
          DUMMY: "1"
        run: pytest -q --cov=YOUR_PACKAGE --cov-report=xml

      - name: Upload coverage.xml
        uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.python-version }}
          path: coverage.xml

      - name: Upload junit report (optional)
        if: always()
        run: pytest --junitxml=pytest-report.xml || true
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: junit-${{ matrix.python-version }}
          path: pytest-report.xml

تکمیل چرخه کیفیت: چک‌های قبل از کامیت

برای کوتاه کردن بازخورد و جلوگیری از ارسال کدهای اشتباه به CI، می‌توانید قبل از کامیت روی سیستم خودتان کد را چک کنید. راهنمای عملی را در راه اندازی Pre-commit Hooks برای بررسی خودکار کد قبل از کامیت ببینید.

گام بعدی برای تسلط روی جریان کاری گیت و گیت هاب

اگر با Git و GitHub تازه کار هستید یا می‌خواهید کار تیمی و Pull Request حرفه‌ای‌تری داشته باشید، مسیر یادگیری شما با آموزش گیت و گیت هاب از صفر تا صد تکمیل می‌شود.

نتیجه نهایی

با یک فایل workflow ساده می‌توانید تست‌های پایتون را در هر Push و Pull Request به صورت خودکار اجرا کنید. از matrix برای پوشش نسخه‌های مختلف پایتون، از کش pip برای سرعت، از گزارش پوشش برای کیفیت و از Secretها برای ایمن نگه داشتن تنظیمات استفاده کنید. از همین امروز فایل .github/workflows/python-tests.yml را بسازید و اولین اجرای سبز را ببینید.