# Pythonの構築とテスト

継続的インテグレーション (CI) ワークフローを作成して、Python プロジェクトをビルドしてテストする方法について説明します。

## はじめに

このガイドでは、Python パッケージをビルド、テスト、発行する方法について説明します。

GitHub によってホストされるランナーは、Python と PyPy を保持しているプリインストール済みソフトウェアと共にツール キャッシュを確保しています。 自分では何もインストールする必要がありません！ 最新のソフトウェアと、Python および PyPy のプリインストール済みのバージョンの完全な一覧については、[GitHub ホステッド ランナー](/ja/enterprise-cloud@latest/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software) を参照してください。

## 前提条件

YAMLとGitHub Actionsの構文に馴染んでいる必要があります。 詳しくは、「[ワークフローの書き込み](/ja/enterprise-cloud@latest/actions/learn-github-actions)」をご覧ください。

Pythonと pip の基本的な理解をお勧めします。 詳細については、以下を参照してください:

* ```
          [Pythonを始める](https://www.python.org/about/gettingstarted/)
  ```
* ```
          [pip パッケージ マネージャー](https://pypi.org/project/pip/)
  ```

## Python ワークフロー テンプレートの使用

すぐに開始するには、リポジトリの `.github/workflows` ディレクトリにワークフロー テンプレートを追加します。

GitHub には、リポジトリに少なくとも 1 つの `.py` ファイルが既に含まれている場合に機能するPythonのワークフロー テンプレートが用意されています。 このガイドの以降のセクションでは、このワークフロー テンプレートをカスタマイズする方法の例を示します。

1. GitHub で、リポジトリのメイン ページに移動します。

2. リポジトリ名の下にある **\[<svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-play" aria-label="play" role="img"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg> Actions]** をクリックします。

   !["github/docs" リポジトリのタブのスクリーンショット。 \[アクション\] タブがオレンジ色の枠線で強調表示されています。](/assets/images/help/repository/actions-tab-global-nav-update.png)

3. ワークフローが既にリポジトリ内にある場合は、 **\[新しいワークフロー]** をクリックします。

4. \[ワークフローの選択] ページには、推奨されるワークフロー テンプレートの選択が表示されます。 "Python アプリケーション" を検索します。

5. \[Python アプリケーション] ワークフローで、**Configure** をクリックします。

6. 必要に応じてワークフローを編集します。 たとえば、Pythonバージョンを変更します。

7. ```
          **[Commit changes]** をクリックします。
   ```

`python-app.yml` ワークフロー ファイルが使用中リポジトリの `.github/workflows` ディレクトリに追加されます。

## Python バージョンの指定

GitHub ホスト ランナー上で Python または PyPy のプレインストールされたバージョンを使うには、`setup-python` アクションを使用します。 このアクションでは、各ランナーのツール キャッシュから特定のバージョンのPythonまたは PyPy を検索し、必要なバイナリを `PATH` に追加します。このバイナリはジョブの残りの部分で保持されます。 特定のバージョンのPythonがツール キャッシュにプレインストールされていない場合、`setup-python` アクションは、[`python-versions`](https://github.com/actions/python-versions) リポジトリから適切なバージョンをダウンロードして設定します。

```
          `setup-python` アクションを使用することは、GitHub Actions でPythonを使用するお勧めの方法です。これは、異なるランナーやPythonのバージョン間で一貫した動作を確保できるためです。 セルフホステッド ランナーを使用している場合は、Pythonをインストールし、`PATH` に追加する必要があります。 詳細については、「[`setup-python`アクション](https://github.com/marketplace/actions/setup-python)」を参照してください。
```

以下の表は、各GitHubホストランナー内でのツールキャッシュの場所です。

<div class="ghd-tool rowheaders">

|   | Ubuntu | Mac | Windows |
| - | ------ | --- | ------- |
|   |        |     |         |

```
          **ツール キャッシュ ディレクトリ** |`/opt/hostedtoolcache/*`|`/Users/runner/hostedtoolcache/*`|`C:\hostedtoolcache\windows\*`|
```

|
**Python ツール キャッシュ**|`/opt/hostedtoolcache/Python/*`|`/Users/runner/hostedtoolcache/Python/*`|`C:\hostedtoolcache\windows\Python\*`|
|
**PyPy ツール キャッシュ**|`/opt/hostedtoolcache/PyPy/*`|`/Users/runner/hostedtoolcache/PyPy/*`|`C:\hostedtoolcache\windows\PyPy\*`|

</div>

セルフホスト ランナーを使用している場合は、`setup-python` アクションを使って依存関係を管理するようにランナーを構成できます。 詳細については、[自己ホストランナーでの setup-python の使用](https://github.com/actions/setup-python#using-setup-python-with-a-self-hosted-runner)に関する`setup-python` README を参照してください。

GitHubは、セマンティックバージョン構文をサポートしています。 詳細については、[セマンティック バージョニングの使用](https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept)と[セマンティック バージョニングの仕様](https://semver.org/)に関するページを参照してください。

### 複数のPython バージョンの使用

次の例では、ジョブのマトリックスを使用して、複数のPython バージョンを設定します。 詳しくは、「[ワークフローでのジョブのバリエーションの実行](/ja/enterprise-cloud@latest/actions/using-jobs/using-a-matrix-for-your-jobs)」をご覧ください。

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["pypy3.10", "3.9", "3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v5
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
```

### 特定のPython バージョンの使用

特定のバージョンのPythonを構成できます。 たとえば、3.12 などです。 あるいは、最新のマイナーリリースを取得するためにセマンティックバージョン構文を使うこともできます。 この例では、Python 3 の最新のマイナー リリースを使用します。

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v5
      - name: Set up Python
        # This is the version of the action for setting up Python, not the Python version.
        uses: actions/setup-python@v5
        with:
          # Semantic version range syntax or exact version of a Python version
          python-version: '3.x'
          # Optional - x64 or x86 architecture, defaults to x64
          architecture: 'x64'
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
```

### バージョンの除外

使用できないPythonのバージョンを指定した場合、`setup-python` は次のようなエラーで失敗`##[error]Version 3.7 with arch x64 not found`。 このエラーメッセージには、利用できるバージョンが含まれます。

実行しないPythonの構成がある場合は、ワークフローで `exclude` キーワードを使用することもできます。 詳しくは、「[GitHub Actions　のワークフロー構文](/ja/enterprise-cloud@latest/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategy)」をご覧ください。

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.11", "3.13", "pypy3.10"]
        exclude:
          - os: macos-latest
            python-version: "3.11"
          - os: windows-latest
            python-version: "3.11"
```

### 既定のPython バージョンの使用

```
          `setup-python` を使用して、ワークフローで使用されるPythonのバージョンを構成することをお勧めします。これは、依存関係を明示的にするのに役立ちます。 
          `setup-python` を使用しない場合、`PATH` を呼び出すときに、`python` で設定された既定のバージョンのPythonが任意のシェルで使用されます。 Pythonの既定のバージョンは、GitHubホストランナーによって異なります。これにより、予期しない変更が発生したり、予想よりも古いバージョンが使用されたりする可能性があります。
```

| GitHubによってホストされているランナー | 説明                                                                                                                                                                                 |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ubuntu                 | Ubuntu ランナーには、`/usr/bin/python` および `/usr/bin/python3` の下に複数のバージョンのシステム Pythonがインストールされています。 Ubuntu にパッケージ化されたPythonバージョンは、GitHub がツール キャッシュにインストールするバージョンに加えてあります。                |
| Windows                | ツール キャッシュ内のPythonのバージョンを除き、Windowsには同等のバージョンのシステム Pythonが付属していません。 他のランナーとの一貫した動作を維持し、`setup-python` アクションなしでPythonをすぐに使用できるようにするために、GitHub はツール キャッシュから `PATH` にいくつかのバージョンを追加します。 |
| macOS                  | macOS ランナーには、ツール キャッシュの一部であるバージョンに加えて、複数のバージョンのシステム Pythonがインストールされています。 システム Pythonバージョンは、`/usr/local/Cellar/python/*` ディレクトリにあります。                                               |

## 依存関係のインストール

GitHubホストランナーには、pipパッケージマネージャーがインストールされています。 コードのビルドとテストに先立って、pipを使ってパッケージレジストリのPyPIから依存関係をインストールできます。 たとえば、以下の YAML では、`pip` パッケージ インストーラーと、`setuptools` および `wheel` パッケージがインストールまたはアップグレードされます。

ワークフローの速度を上げるために、依存関係をキャッシュすることもできます。 詳しくは、「[依存関係キャッシュのリファレンス](/ja/enterprise-cloud@latest/actions/using-workflows/caching-dependencies-to-speed-up-workflows)」をご覧ください。

```yaml copy
steps:
- uses: actions/checkout@v5
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: python -m pip install --upgrade pip setuptools wheel
```

### 要件ファイル

```
          `pip` の更新後、一般的な次の手順は、`requirements.txt` から依存関係をインストールすることです。 詳しくは、「[pip](https://pip.pypa.io/en/stable/cli/pip_install/#example-requirements-file)」をご覧ください。
```

```yaml copy
steps:
- uses: actions/checkout@v5
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
```

### 依存関係のキャッシング

```
          [
          `setup-python`アクション](https://github.com/actions/setup-python)を使用して依存関係をキャッシュおよび復元できます。
```

次の例では pip の依存関係をキャッシュします。

```yaml copy
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
    cache: 'pip'
- run: pip install -r requirements.txt
- run: pip test
```

既定で、`setup-python` アクションでは、リポジトリ全体で依存関係ファイル (pipは `requirements.txt`、pipenvは `Pipfile.lock`、poetryは `poetry.lock`) を検索します。 詳細については、`setup-python` の README の「[パッケージの依存関係のキャッシュ](https://github.com/actions/setup-python#caching-packages-dependencies)」をご覧ください。

カスタム要件がある場合、またはキャッシュに対してより細かい制御が必要な場合は、[`cache` アクション](https://github.com/marketplace/actions/cache)を使用できます。 ランナーのオペレーティングシステムによって、pipは依存関係を様々な場所にキャッシュします。 キャッシュする必要があるパスは、使用するオペレーティング システムによって、上記の Ubuntu の例とは異なる場合があります。 詳細については、[](https://github.com/actions/cache/blob/main/examples.md#python---pip) アクション リポジトリの`cache`を参照してください。

## コードのテスト

ローカルで使うのと同じコマンドを、コードのビルドとテストに使えます。

### pytest及びpytest-covでのテスト

この例では、`pytest` および `pytest-cov` をインストールまたはアップグレードします。 そしてテストが実行され、JUnit形式で出力が行われ、一方でコードカバレッジの結果がCoberturaに出力されます。 詳細については、[JUnit](https://junit.org/junit5/) と [Cobertura](https://cobertura.github.io/cobertura/) に関するページを参照してください。

```yaml copy
steps:
- uses: actions/checkout@v5
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
- name: Test with pytest
  run: |
    pip install pytest pytest-cov
    pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html
```

### Ruff を使用してコードのリントや書式設定を行う

以下の例では、`ruff` をインストールまたはアップグレードし、それを使ってすべてのファイルを lint します。 詳しくは、「[Ruff](https://docs.astral.sh/ruff)」を参照してください。

```yaml copy
steps:
- uses: actions/checkout@v5
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install the code linting and formatting tool Ruff
  run: pipx install ruff
- name: Lint code with Ruff
  run: ruff check --output-format=github --target-version=py39
- name: Check code formatting with Ruff
  run: ruff format --diff --target-version=py39
  continue-on-error: true
```

書式設定ステップが `continue-on-error: true` に設定されています。 これにより、書式設定ステップが成功しなかった場合にワークフローが失敗しなくなります。 すべての書式設定エラーに対処したら、ワークフローで新しい問題を見つけられるようにこのオプションを削除できます。

### toxでのテストの実行

GitHub Actionsでは、toxでテストを実行し、その処理を複数のジョブに分散できます。 特定のバージョンを指定するのではなく、`-e py` オプションを使用して tox を呼び出して、`PATH` のPythonのバージョンを選択する必要があります。 詳細については、[tox](https://tox.readthedocs.io/en/latest/) に関するページを参照してください。

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python: ["3.9", "3.11", "3.13"]

    steps:
      - uses: actions/checkout@v5
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python }}
      - name: Install tox and any other packages
        run: pip install tox
      - name: Run tox
        # Run tox using the version of Python in `PATH`
        run: tox -e py
```

## 成果物としてのワークフローのデータのパッケージ化

ワークフローの完了後に、成果物をアップロードして見ることができます。 たとえば、ログファイル、コアダンプ、テスト結果、スクリーンショットを保存する必要があるかもしれません。 詳しくは、「[ワークフロー成果物を使ったデータの格納と共有](/ja/enterprise-cloud@latest/actions/using-workflows/storing-workflow-data-as-artifacts)」をご覧ください。

以下の例は、`upload-artifact` アクションを使って `pytest` の実行によるテスト結果をアーカイブする方法を示しています。 詳細については、「[`upload-artifact`アクション](https://github.com/actions/upload-artifact)」を参照してください。

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v5
      - name: Setup Python # Set Python version
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # Install pip and pytest
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
      - name: Test with pytest
        run: pytest tests.py --doctest-modules --junitxml=junit/test-results-${{ matrix.python-version }}.xml
      - name: Upload pytest test results
        uses: actions/upload-artifact@v4
        with:
          name: pytest-results-${{ matrix.python-version }}
          path: junit/test-results-${{ matrix.python-version }}.xml
        # Use always() to always run this step to publish test results when there are test failures
        if: ${{ always() }}
```

## PyPI への発行

CI テストに合格したら、Python パッケージを PyPI に発行するようにワークフローを構成できます。 このセクションでは、GitHub Actions を使用して、リリースを公開するたびにパッケージを PyPI にアップロードする方法について説明します。 詳しくは、「[リポジトリのリリースを管理する](/ja/enterprise-cloud@latest/repositories/releasing-projects-on-github/managing-releases-in-a-repository)」をご覧ください。

次のワークフロー例では、[信頼された出版を設定する](https://docs.pypi.org/trusted-publishers/) を使用して PyPI で認証を行います。これには、手動で構成された API トークンは不要です。

```yaml copy
# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

name: Upload Python Package

on:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  release-build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v5

      - uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Build release distributions
        run: |
          # NOTE: put your own distribution build steps here.
          python -m pip install build
          python -m build

      - name: Upload distributions
        uses: actions/upload-artifact@v4
        with:
          name: release-dists
          path: dist/

  pypi-publish:
    runs-on: ubuntu-latest

    needs:
      - release-build

    permissions:
      # IMPORTANT: this permission is mandatory for trusted publishing
      id-token: write

    # Dedicated environments with protections for publishing are strongly recommended.
    environment:
      name: pypi
      # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
      # url: https://pypi.org/p/YOURPROJECT

    steps:
      - name: Retrieve release distributions
        uses: actions/download-artifact@v5
        with:
          name: release-dists
          path: dist/

      - name: Publish release distributions to PyPI
        uses: pypa/gh-action-pypi-publish@6f7e8d9c0b1a2c3d4e5f6a7b8c9d0e1f2a3b4c5d
```

必要な PyPI 設定など、このワークフローの詳細については、「[PyPI での OpenID Connect の構成](/ja/enterprise-cloud@latest/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-pypi)」を参照してください。