はじめに
皆さん競技プログラミングを楽しんでいますか?しばらくやっているとそのうち自作ライブラリを作りたくなりますよね!ところが、自作ライブラリの実装にミスがあると本番で悲惨なことに...。
それを避けるためにもテストをするかと思います。ところが、テストをするのを忘れて正しくないコードを GitHub に push してしまうことも...。私の場合はリファクタリングをする際にやりがちです。それならば push したタイミングでテストが自動で行われるようにし、テスト失敗時にメールが届くようにすれば良いのでは!?これこそが今回紹介する内容です。
CI/CD と GitHub Actions について
自作ライブラリのように高品質のソフトウェアを長期に渡って開発し、その価値を提供するためには CI/CD が欠かせません。参考文献に挙げている文献 [1] によると、CI/CD はビルドからリリースまでを自動化するものです。CI が「継続的インテグレーション」、CD が「継続的デリバリー」を指します。具体的には CI は、変更したコードをコードベースへ取り込み、検証する営みを指します。CD は、いつでも安全にリリースできる状態を保ち、ソフトウェアを繰り返し改善する営みを指します。
GitHub Actions は GitHub が提供している CI/CD を実現するサービスの 1 つです。後述しますが、YAML で記述したワークフローファイルを当該リポジトリの .github/workflows ディレクトリ内に作成することで CI/CD を実現できます。
GitHub Actions で Hello, World!
プログラミング言語を学ぶ時と同様に、まずは Hello, World! を出力するワークフローを作成してみましょう。空のリポジトリを用意し、次のような YAML ファイルを作成します。
name: Hello World # ワークフローの名前
on: push # イベント
jobs: # ジョブ
hello: # ジョブ ID
runs-on: ubuntu-latest # ランナー(実行環境)
steps: # ステップ(処理の最小単位)
- run: echo "Hello, World!" # シェルコマンド
hello-world.yaml を GitHub へ push し、当該リポジトリの Actions から hello を開くと次のように Hello, World! が出力されていることが分かるかと思います。
GitHub Actions による Python の自動テスト
Python の自作ライブラリに対する自動テストを行うには次のような test.yaml を記述すれば良いです。GitHub への push 時に Python ファイルの変更が含まれる場合のみテストが自動で行われるようになっています。
name: Test
on:
push:
paths: ["**/*.py"]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # リポジトリのコードを取得する
- uses: actions/setup-python@v5 # Python のセットアップ
with:
python-version: "3.11"
- name: Run Test # src 配下の test_*.py に対してテストを行う
run: |
python -m unittest discover -s src -p "test_*.py"
試しに、足し算の関数 add を実装し、それに対するテストを作成してみましょう。
def add(x: int, y: int) -> int:
return x + y
import unittest
from add import add
class TestPrime(unittest.TestCase):
def test_add(self):
"""足し算のテスト"""
self.assertEqual(2, add(1, 1))
self.assertEqual(1, add(1, 0))
self.assertEqual(1, add(0, 1))
self.assertEqual(1, add(2, -1))
self.assertEqual(-1, add(1, -2))
self.assertEqual(-2, add(-1, -1))
self.assertEqual(5, add(2, 3))
self.assertEqual(-10, add(-4, -6))
self.assertEqual(1, add(1000000000001, -1000000000000))
self.assertEqual(-1, add(-987654321, 987654320))
self.assertEqual(200000000000, add(50000000000, 150000000000))
self.assertEqual(-400000000000, add(-150000000000, -250000000000))
これらを GitHub へ push してみると次のようにテストが自動で実行されていることが分かります。
ここで add.py の内容を次のように変えてテストに失敗するかを確認してみましょう。
def add(x: int, y: int) -> int:
- return x + y
+ return x * y
変更した add.py を GitHub へ push すると確かに失敗していることが分かります。add(1, 1) すなわち 1 + 1 の結果が 2 になることを期待したのに 1 だったよ!と言われていますね。
さらにメールも届いています。
最後に
GitHub Actions がどういうものなのか知らなかったけど便利だな〜!自分も今度使ってみよう!と思っていただければ嬉しいです。
参考文献
[1] 野村友規(2024)『GitHub CI/CD 実践ガイド 持続可能なソフトウェア開発を支える GitHub Actions の設計と運用』技術評論社



