0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

負債化しないシェルスクリプト設計:GitHub Actionsでbatsの自動テスト・カバレッジの取得

0
Posted at

はじめに

前回の記事では、Bashスクリプトに「Functional Core, Imperative Shell(FCIS)」のアーキテクチャを取り入れ、bats-core を使ってテスト可能な状態にする手法を解説しました。

今回はその続編として、テストを CI(GitHub Actions)で自動化し、kcov を用いてカバレッジ率を計測する 方法をご紹介します。

また、ローカル環境とCI環境でのツール群のバージョンやコマンド差異を防ぐため、最近人気を集めているツールマネージャー mise を用いて環境構築とタスク実行を統一します。

概要・前提条件

本記事では以下のツールを使用します。

  • bats-core : Bash用のテストフレームワーク
  • kcov : コンパイル言語だけでなく Bashスクリプトの網羅率(カバレッジ)も計測できるツール
  • mise : でプロジェクトのツール群とタスクを一元管理するマネージャー

本記事では、kcov がローカル環境にインストールされていることを前提としています。

kcov は Ubuntu 24.04 などでは OS のパッケージマネージャーで配布されなくなっているので、公式のインストール手順 を参考にビルドするか、公式提供の Docker image を利用することになります

本題・実装

1. サンプルコードの準備

まずはカバレッジの「通っている行」「通っていない行」を可視化するための簡単なサンプルを用意します。
足し算と引き算の関数を持つ math.sh と、足し算だけをテストする test_math.bats を作成します。

math.sh
#!/usr/bin/env bash

add() {
  echo $(($1 + $2))
}

subtract() {
  # この関数はテストから呼ばれないため、カバレッジ上は「未実行」になる
  echo $(($1 - $2))
}
test_math.bats
#!/usr/bin/env bats

setup() {
  source ./math.sh
}

@test "add function should return sum" {
  run add 2 3
  [ "$status" -eq 0 ]
  [ "$output" = "5" ]
}

2. miseを使ったローカル環境とタスクの構築

今回は bats-core をツールマネージャー mise で管理し、テスト実行コマンドを mise のタスクとして定義します。

カバレッジ取得には、ローカル環境にインストールされた kcov を使用します。

以下の内容でプロジェクトルートに mise.toml を作成します。

mise.toml
[tools]
"aqua:bats-core/bats-core" = "1.11.0"

[tasks.test]
description = "Run bats tests"
run = "bats ./test_math.bats"

[tasks.coverage]
description = "Run tests and generate kcov coverage report"
run = "kcov --include-pattern=.sh coverage/ bats ./test_math.bats"

設定ができたら、mise install を実行してツール群をインストールします。

$ mise install

これにより、mise.toml に定義したコマンドを mise run 経由で呼び出せるようになります。

$ mise run coverage

# (実行結果例)
# kcov がローカルで bats を実行し、coverage/ ディレクトリにレポートを生成します
# ✓ add function should return sum
# 
# 1 test, 0 failures

実行後、coverage/ ディレクトリ内にHTML形式のレポートが出力されます。

image.png

キャプチャを見ると、add 関数の行が緑色(実行済み)、subtract 関数の行が赤色(未実行)になっていることが確認できるはずです。

3. GitHub Actions ワークフローの実装

ローカルで動くようになったら、これを GitHub Actions に組み込みます。

CI上でも公式アクション jdx/mise-action を利用することで、ツールのセットアップからタスクの実行までを非常にシンプルに記述できます。

さらに、CI環境ではテスト結果を見やすくするため、bats の出力を JUnitフォーマット に変換するのもおすすめです。

今回はテスト結果(JUnit XML)を出力するタスク ci-test を追加して、結果をGitHub Actions上で可視化する構成にします。(※CI環境でのカバレッジ取得については後述の課題があるため、今回はテストの実行のみを扱います)

mise.toml にCI用のタスクを追記します。

mise.toml
[tasks.ci-test]
description = "Run tests and output JUnit XML"
# batsの --formatter junit を使い、結果を report.xml に書き出します
run = '''
rm -f report.xml
bats --formatter junit ./test_math.bats > report.xml
'''

これを GitHub Actions のワークフローで呼び出します。

※テスト用なので GitHub Actions Workflow のセキュリティ面は厳密に考慮した記述になっていません。例えばActions をバージョンタグで呼び出していますが、実運用では suzuki-shunsuke/pinact などを利用して SHA1 Hash で指定バージョンを固定してください

.github/workflows/test.yml
name: Bash Tests

on:
  push:
    branches: [ "main" ]
  pull_request:

permissions:
    contents: read
    checks: write

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup tools with mise
        uses: jdx/mise-action@v4

      - name: Run CI test task
        run: mise run ci-test

      # JUnitレポートを解釈してPR等にテスト結果を表示するアクション
      - name: Publish Test Report
        uses: mikepenz/action-junit-report@v6
        if: success() || failure()
        with:
          report_paths: 'report.xml'
          include_passed: 'true'

ポイント:

  • jdx/mise-action を使うことで、ローカルと同じインストール手順でインストールができます
  • bats --formatter junit を指定して report.xml を出力し、mikepenz/action-junit-report(または同等のアクション)に渡すことで、GitHub上で「何ケース成功して何ケース失敗したか」の数値をグラフィカルに確認できるようになります

4. テスト結果の確認

GitHub Actionsの実行が完了すると

Pull Request の Check の Bash Tests / JUnit Test Report (pull_request) の項目にテストの失敗・成功

image.png

ワークフローの「Summary」ページにテストの成功・失敗の件数や詳細がグラフィカルに表示されます。

image.png

ローカルでは mise run coverage でカバレッジを確認しつつ、CIではプルリクのたびに自動テストが走ってコードの健全性を担保する、というワークフローがこれで完成です。

おわりに & CI 環境でのカバレッジ取得の課題

前回の「FCISなアーキテクチャによるテスト容易性の確保」に続き、本記事では 「mise を使った環境・タスクの統一」 を行い、ローカルでの bats テストと kcov によるカバレッジ取得環境を整備しました。

一方で、このカバレッジ計測を GitHub Actions 上で実践しようとすると、kcov のインストールが意外と厳しい という課題があります。

OSの公式パッケージを apt-get でインストールしようとするとバージョンが古かったり、逆にソースから都度ビルドするとCIの実行時間が延びてしまう等の悩ましさがあります。

手軽に導入できそうな第三者のアクション(例えば action-kcov )も存在しますが、中身を見ると2020年に作られたコードに latest (07/2024) などの新しいタグだけが付けられて更新されているような状態で、プロダクションでの積極的な利用はおすすめしづらいと感じました。

そのため、本記事の GitHub Actions ワークフローでは kcov の実行を見送り純粋なテストのみの構成としましたが、今後は「CI上でもカバレッジを取得できる方法」を引き続き探していきたいと考えています。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?