CI/CD テスト自動化の導入手順と実装方法

はじめに
「リリースのたびに手動テストが大変」「テストをサボると後で大炎上する」
そんな悩みを解決するキーワードが 「CI/CD テスト自動化」 です。
CI/CD とテスト自動化を組み合わせることで、
- プルリク作成 → 自動ビルド → 自動テスト → 自動デプロイ
という流れを機械に任せられるようになり、 - バグの早期発見
- 手動テストの削減
- 安全な高頻度リリース
を同時に実現できます。
この記事では、「ci/cd テスト自動化」をこれから導入する方に向けて、
- 基本概念
- 導入前準備
- CI/CD パイプラインの構築手順
- テスト自動化の実装方法(GitHub Actions の例つき)
- 継続運用のポイント
までを、できるだけ実装レベルに落として解説します。
CI/CDとテスト自動化の基本概念
CI/CDとは何か
CI(Continuous Integration:継続的インテグレーション)
- 開発者がこまめに Git ブランチへコードをマージする
- そのタイミングで自動的に
- ビルド
- 静的解析
- テスト
を実行する仕組みです。
目的は、問題を早期に発見し、壊れたコードが積み上がらないようにすること です。
CD(Continuous Delivery / Deployment:継続的デリバリー / デプロイメント)
- CI を通ったコードを、ステージングや本番に
- 半自動(人が最終ボタンを押す)
- 完全自動
でデプロイする仕組みです。
- Continuous Delivery:
→ 本番リリース前に人が承認する - Continuous Deployment:
→ テストが通れば自動で本番まで流す
テスト自動化との関係性
CI/CD は「パイプライン(流れ)」の設計です。
そこに テスト自動化 を組み込むことで、はじめて本領を発揮します。
- コード変更 → PR 作成
- CI が自動ビルド・自動テストを実行
- 問題がなければ CD がデプロイまで進める
これを「毎回同じ条件で、機械的に」行うことで、
- 人によるテスト漏れ防止
- テストの品質・粒度の標準化
- テストが通らない限りマージさせない運用
が可能になります。
CI/CD テスト自動化の導入前準備
現状のテスト環境の評価
ツール導入の前に、まずは 「今どこまでテストができているか」 を確認します。
- 自動テストの有無
- 単体テスト(ユニットテスト)はあるか
- 統合テスト / E2E テストはあるか
- テストの手順
- 手動でチェックしている項目は何か
- テストにどれくらい時間がかかっているか
- 課題
- いつもバグが出る箇所はどこか
- 「ここが壊れるとまずい」クリティカルな機能はどこか
おすすめは「全部を一気に自動化しない」ことです。
まずは、
- よく壊れる部分
- 壊れるとビジネスインパクトが大きい部分
から優先的にテスト自動化の対象にしていきます。
必要なツールとインフラの選定
次に、「何を使って ci/cd テスト自動化を構築するか」を決めます。
代表的な選択肢は以下の通りです。
- バージョン管理
- GitHub / GitLab / Bitbucket など
- CI/CD ツール
- GitHub Actions
- GitLab CI/CD
- CircleCI
- Jenkins など
- テストフレームワーク
- PHP:PHPUnit / Pest
- JavaScript:Jest / Vitest / Playwright / Cypress
- Ruby:RSpec
- Java:JUnit
- など、言語に応じて選択
- 実行環境
- SaaS 型ランナー(GitHub Actions / CircleCI など)
- 独自のビルドサーバ(オンプレ / 自社クラウド)
- デプロイ先
- AWS / GCP / Azure
- Vercel / Netlify
- 共有サーバ / VPS など
多くのチームでは、GitHub + GitHub Actions という組み合わせが特に多いため、
この記事でも後半の実装例は GitHub Actions をベースに説明します。
CI/CDパイプラインの構築手順
ステップ1: バージョン管理システムの設定
CI/CD テスト自動化の前提として、まずは Git 運用を整える ことが重要です。
- メインブランチの定義
main:常にデプロイ可能な状態develop:開発用(必要に応じて)
- ブランチルール
- 新機能:
feature/xxx - バグ修正:
fix/xxx
- 新機能:
- プロテクトブランチ
mainやdevelopへの直接 push を禁止- PR(Pull Request)経由でのみマージ
- 「テストが通らないとマージできない」設定を有効化
この時点で、「コード変更 = PR」→「PR 作成 = CI トリガー」 という流れを作れるようになります。
ステップ2: ビルド自動化の実装
次は、GitHub Actions を例に「ビルド自動化」を実装していきます。
- リポジトリ内に
.github/workflows/ci.ymlファイルを作成 - 以下のような最小構成を書く(例:Node.js + テスト)
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: リポジトリのチェックアウト
uses: actions/checkout@v4
- name: Node.js のセットアップ
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 依存パッケージのインストール
run: npm install
- name: ビルド
run: npm run build
PHP/Laravel の場合であれば、ビルド部分を composer install や php artisan コマンドに置き換えます。
- name: PHP のセットアップ
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Composer install
run: composer install --no-interaction --prefer-dist
この時点ではまだテストを実行していませんが、
- PR / push のたびに
- 依存インストール〜ビルドまでを自動で確認
できる状態になります。
ステップ3: テスト自動化の統合
ビルドが安定して動くようになったら、
次は テストコマンドを CI に組み込み ます。
例:PHPUnit(PHP)の場合
- name: テスト実行(PHPUnit)
run: |
cp .env.ci .env
php artisan key:generate
php artisan test
例:Jest(フロントエンド)の場合
- name: テスト実行(Jest)
run: npm test
最終的なイメージは以下のようになります。
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 言語ごとのセットアップ ...
- name: 依存パッケージのインストール
run: npm install
- name: ビルド
run: npm run build
- name: テスト実行
run: npm test
GitHub 側で
- 「この workflow がグリーンでないと main にマージできない」
というブランチ保護ルールを設定しておけば、
テストが落ちている PR はそもそもマージできない 状態を作れます。
テスト自動化の実装方法
ここからは、テストコードそのものの実装方法 に踏み込んでいきます。
「ci/cd テスト自動化」を実現するためには、
- テストコードを書く
- ローカルでテストを回せるようにする
- そのコマンドを CI に組み込む
という 3 ステップが基本になります。
単体テストの自動化
単体テストは、関数やメソッド単位での振る舞いを確認するテスト です。
単体テストの基本イメージ(例:PHPUnit)
// tests/Unit/PriceCalculatorTest.php
use Tests\TestCase;
use App\Services\PriceCalculator;
class PriceCalculatorTest extends TestCase
{
/** @test */
public function 税込み価格が正しく計算できる()
{
$calculator = new PriceCalculator();
$actual = $calculator->withTax(1000, 0.1); // 10% 税
$this->assertSame(1100, $actual);
}
}
ポイントは以下の通りです。
- 「この入力に対して、この出力になる」という形でテストを書く
- 外部サービスや DB などはモック/スタブで切り離す
- 1 テストケース = 1 つの振る舞いに絞る
単体テストを CI に載せる
ローカルで php artisan test や npm test が通る状態になったら、
そのまま CI のジョブにコマンドとして登録します。
- ローカル:
php artisan test - GitHub Actions:
run: php artisan test
という対応関係を意識すると、実装がわかりやすくなります。
統合テストの自動化
統合テストは、複数のコンポーネントをまとめて動かしたときに正しく連携するか を確認するテストです。
- Web アプリなら
- リクエスト → ルーティング → コントローラ → サービス → DB
- API なら
- エンドポイントにリクエスト → 正しい JSON が返るか など
統合テストの例(API のレスポンス確認)
// tests/Feature/OrderApiTest.php
use Tests\TestCase;
use App\Models\Order;
class OrderApiTest extends TestCase
{
/** @test */
public function 注文一覧APIで注文が取得できる()
{
// テスト用データを作成
Order::factory()->count(3)->create();
// API にアクセス
$response = $this->getJson('/api/orders');
// ステータスコードと JSON 構造を検証
$response
->assertStatus(200)
->assertJsonCount(3, 'data');
}
}
CI で統合テストを回すときのポイント
- DB を使うので、CI 上でテスト用 DB を用意する
- MySQL / PostgreSQL / SQLite in memory など
- マイグレーションを実行してからテストする
例:GitHub Actions でのイメージ
- name: DB マイグレーション
run: php artisan migrate --env=testing --force
- name: 統合テスト実行
run: php artisan test --testsuite=Feature
統合テストは実行時間が長くなりがちなので、
- すべての PR で回すのか
- main へのマージ時だけフルセットを回すのか
など、負荷とカバレッジのバランスを調整 するのがポイントです。
CI/CDテスト自動化を継続するためのポイント
「一度構築して終わり」ではなく、運用しながら育てていく意識 が大切です。
- テストが落ちたら必ず原因を追う
- 「たまに落ちるから無視」は絶対にNG
- CI への信頼性が一気に落ちる
- フレークテストを放置しない
- 外部サービスへの依存が強すぎる
- 時間に依存している(今日だけ落ちる)
などの要因があれば、テスト設計を見直す
- 新機能には必ずテストをセットにする
- Definition of Done に「テストが書かれていること」を含める
- 「テストを書かないとマージできない」運用にする
- CI の実行時間を定期的に見直す
- 10 分を超えてくると開発体験が悪化しやすい
- キャッシュ・テスト分割・夜間バッチなどの工夫を行う
- 可視化とフィードバック
- CI のステータスを PR 上で一目でわかるようにする
- Slack などへ通知して、チーム全体で気にする文化を作る
まとめ
この記事では、「CI/CD テスト自動化の導入手順と実装方法」というテーマで、
- CI/CD とテスト自動化の基本概念
- 導入前準備(現状の棚卸しとツール選定)
- GitHub Actions を例にした CI/CD パイプライン構築手順
- 単体テスト・統合テストの具体的な実装イメージ
- CI/CD テスト自動化を継続するための運用ポイント
を紹介しました。
タイトル通りの「実装方法」まで含めるために、
.github/workflows/ci.ymlの実例- テストコード(単体 / 統合)のサンプル
- CI への組み込み手順
といった 手を動かせるレベルの情報 も盛り込んでいます。
最初から完璧なパイプラインを目指す必要はありません。
まずは、
- ローカルでテストを回せるようにする
- 単体テストを GitHub Actions に載せる
- 重要な API や画面の統合テストを一部だけ自動化する
という小さなステップから始めて、
自分たちのチームに合った「ci/cd テスト自動化」を育てていきましょう。
