OpenAPIの思想を応用!YAMLとGo言語でテスト仕様書をGit管理し、開発効率を劇的に向上させる方法

はじめまして!DXビジネス開発部の宍戸です。

普段はOPTiM Collaboration Portalというプロダクトのバックエンドエンジニアとして開発をしています。

本記事は OPTiM TECH BLOG Advent Calendar 2025 Day 9 の記事です。

はじめに

私たちのプロジェクトではリリースごとにExcelでテスト仕様書を作成して検証を実施しています。 テスト仕様書はその都度マスターとなるExcelファイルが存在しており、そのテンプレートなどは別のExcelで管理されています。

リグレッションやバグが出た時の変更差分を確認する際に、変更履歴が出ないと情報が追いづらいと感じていました

上記を解決する手段として、Git管理ができる方法を考えていましたが、OpenAPIから着想を経て、最終的にはYAMLでの管理をすることにしました。

YAMLでテスト仕様書管理

既存の運用だと、Excelでは、1シート1機能で項目が存在するため、機能ベースでyamlファイルを分けて、それをExcelのシートとして出力すると現行の方法に沿った仕様書ができると思いました。

そのため、OpenAPIのファイル分割での運用を取り入れたいと思います

spec/
├── master.yaml              # メイン設定ファイル
├── excel_columns.yaml       # Excel列設定
└── features/                # 機能ごとのテストケース
    ├── user/
    │   ├── profile.yaml
    │   ├── login.yaml
    │   └── logout.yaml

$ref参照によるインクルード管理

master.yaml で各機能のYAMLファイルを $ref を使ってインクルードしています

ディレクトリの分け方としてはfeature/{機能種別}/{機能}としております

# master.yaml

meta:
  project: "Collaboration Portal"
  version: "0.0.1"

# 読み込むテストケース定義ファイル
# OpenAPIスタイルの$ref参照をサポート
includes:
  - $ref: "./features/user/profile.yaml"
  - $ref: "./features/user/login.yaml"
  - $ref: "./features/user/logout.yaml"

YAMLの記述例

実際のテストケースは以下のような形式で記述しています

# features/user/login.yaml
# 機能ごとのテストケース定義ファイル

feature: "ログイン"  # 機能名(Excelのシート名として使用)

cases:
  - id: "001"
    title: "ログイン成功"
    feature: "ログイン"
    preconditions: |
      ユーザー test@example.com が存在している
      パスワードが設定されている
    step: |
      1. ログイン画面にアクセスする
      2. メールアドレスとパスワードを入力する
      3. ログインボタンをクリックする
    expecterresult: |
      ダッシュボード画面が表示されること
      ユーザー名が表示されること
    result: ""
    related_ticket: ""

  - id: "002"
    title: "ログイン失敗(パスワード誤り)"
    feature: "ログイン"
    preconditions: |
      ユーザー test@example.com が存在している
    step: |
      1. ログイン画面にアクセスする
      2. メールアドレスと誤ったパスワードを入力する
      3. ログインボタンをクリックする
    expecterresult: |
      エラーメッセージが表示されること
      ログインできないこと
    result: ""
    related_ticket: ""

この内容のアウトプットとしては各ヘッダーに対しての期待値などとして以下の画像のように出力されます

実装

YAMLをExcelに変換する際にはCLIツールを使用します。実装言語にはGo言語を選択しました。 先述しましたが、Excelファイルをテスト仕様書として運用をしているので出力はExcelとして対応することにします。

選択理由としては、プロダクトでGoを利用しているので書き馴染みがあり、Excelの特定の列や表に対する操作ができる点が挙げられます。 YAMLからExcelへの生成処理は、Cobraを使用してCLIコマンドとして実装しています。 現在の実装ではCLIとして機能を拡充しているわけではないのでCobraでどういうことをしているかの詳細は省きます。

主要機能

1. Excel/CSV生成

読み込んだテストケースを機能ごとにグループ化し、Excelファイルとして出力します。各機能は別々のシートとして生成されます。

// GenerateExcel Excelファイルの生成(機能ごとにシート分け)
func (g *excelGenerator) GenerateExcel(featureGroups []models.FeatureGroup, version string, projectName string, outputDir string) (string, error) {
    // Excelワークブックを作成
    workbook := excelize.NewFile()

    // 機能ごとにシートを作成してデータを書き込み
    for _, group := range featureGroups {
        sheetName := g.sanitizeSheetName(group.FeatureName)

        // シートを作成
        g.CreateSheet(workbook, sheetName)

        // ヘッダー行を書き込み
        g.WriteHeaders(workbook, sheetName)

        // テストケースデータを書き込み
        g.WriteTestCases(workbook, sheetName, group.TestCases)
    }

    // Excelファイルを保存
    return filePath, nil
}

CSVファイルも同様に生成され、バージョンごとにディレクトリが分けられて保存されます。

2. HTMLビューワー

生成されたファイルをブラウザで確認できるWebサーバー機能を実装しています。

// Start サーバーを起動
func (s *Server) Start() error {
    mux := http.NewServeMux()

    // ルートパス: ファイル一覧を表示
    mux.HandleFunc("/", s.handleIndex)

    // CSVファイルをHTMLテーブルとして表示
    mux.HandleFunc("/view/csv/", s.handleViewCSV)

    // Excelファイルをダウンロード
    mux.HandleFunc("/download/excel/", s.handleDownloadExcel)

    return http.ListenAndServe(addr, mux)
}

HTMLビューワーでは以下のことができます:

  • 生成されたExcel/CSVファイルの一覧表示
  • CSVファイルをブラウザ上でテーブル表示
  • Excelファイルのダウンロード

HTMLは埋め込みテンプレートとして実装し、外部ファイルへの依存なしで動作します

html := `<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>SpecSheet - Generated Files</title>
    <style>
        /* モダンなスタイリング */
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        /* ... */
    </style>
</head>
<body>
    <h1>📊 SpecSheet - Generated Files</h1>
    <!-- ファイル一覧 -->
</body>
</html>`

このようにHTMLの埋め込みを利用すると以下のように表示することができます

4. バージョン管理

出力については基本的にはMakeFileで行っています。 Cobraのコマンドをたたくようなmakeコマンドを定義して、そこから生成物を出力します。

テスト仕様書はバージョンごとにファイルを生成することでどのバージョンでの項目であるかを明示的に表現します

# バージョンを指定して生成
make generate VERSION=0.0.1

# 生成されるファイル構造
output/
├── Collaboration_Portal_v0.0.1.xlsx
└── version/
    └── v0.0.1/
        ├── ユーザープロフィール.csv
        ├── ログイン.csv
        ├── ログアウト.csv
        └── ...

ローカルで実行して生成した内容はあくまで仮のテスト仕様書と定義して、CI/CDで作成された結果がテスト仕様書として定義されます。

チーム内のレビューが完了してマージされた場合に、その結果を正として検証を実施していきます

  1. YAMLファイルの検証: 構文エラーや参照エラーがないかチェック
  2. 成果物の保存: 生成されたファイルをGitLabのArtifactsとして保存し、ダウンロード可能にする
# .gitlab-ci.yml の例
generate_spec:
  stage: build
  image: golang:1.21
  script:
    - make generate-ci VERSION=${CI_COMMIT_TAG:-dev} ARTIFACT_PATH=artifacts
  artifacts:
    paths:
      - artifacts/*.xlsx
      - artifacts/version/
    expire_in: 30 days
  only:
    - main
    - tags

作成されたExcelの一部ですが、以下のように表示されます。

最後に

まだ運用の余地は多くある段階ではありますが、Cursorとのタブ補完を利用することでテスト仕様書を書くスピードはかなり上がりました 今後もAI活用などを円滑にするための改善を推進していこうと思います

一緒に技術的なチャレンジを楽しんでくれる方、ぜひご応募ください!

www.optim.co.jp