🏃 技術調査 - Runn
目次

🏃 技術調査 - Runn

概要

API のシナリオテストを書くとき、HTTP だけでなく gRPC やデータベースの検証も 1 つのツールでまとめて実行したいと感じたことはありませんか。runn は、YAML ファイル(ランブック)にシナリオを記述し、複数ステップの操作を順序通りに実行する Go 製のテスト・自動化ツールです。

位置づけ: Go 言語実装のシナリオベース統合テスト・ワークフロー自動化フレームワーク

リポジトリ: k1LoW/runn

用途 説明
統合テスト 複数プロトコルをまたぐ E2E テストの定義・実行
ワークフロー自動化 定義したシナリオの自動実行
Go テストヘルパー httptest.Serversql.DB と組み合わせた組み込み利用

特徴

  • マルチプロトコル対応: HTTP/REST、gRPC、SQL DB、Chrome DevTools Protocol、SSH、ローカルコマンドを単一ツールで操作できます
  • YAML 宣言記述: ランブックを YAML 形式で記述し、ステップ間のデータ受け渡しを {{ steps[N].res.body }} で参照できます
  • OpenAPI 検証: HTTP リクエスト/レスポンスを OpenAPI 3.x 仕様に対して自動検証できます
  • 式言語によるアサーション: expr-lang/expr を利用した動的変数展開とテスト条件評価ができます
  • 柔軟な実行制御: 条件付き実行(if)、ループ・リトライ、遅延実行(defer)、並行実行に対応しています
  • シナリオ自動生成: runn new コマンドで既存の curl や grpcurl コマンドからシナリオを生成できます
  • 単一バイナリ: CI パイプラインへの組み込みが容易です
  • デュアルインターフェース: CLI ツール(runn run)と Go ライブラリ(runn.Load() / runn.Run())の両方として利用できます

構造

システムコンテキスト図

Runbook を定義・実行 REST リクエスト gRPC リクエスト SQL クエリ CDP 操作 SSH コマンド コマンド実行 開発者 / テスト担当者 Runn HTTP サービス gRPC サービス データベース ブラウザ リモートホスト ローカルシェル
要素名 説明
開発者 / テスト担当者 Runbook を記述し、Runn を実行するユーザー
Runn シナリオベースのオペレーション実行ツール本体
HTTP サービス REST API を提供する外部 Web サービス
gRPC サービス Protocol Buffers ベースの RPC サービス
データベース MySQL / PostgreSQL / SQLite / Cloud Spanner 等の SQL データベース
ブラウザ Chrome DevTools Protocol で操作対象となるブラウザ
リモートホスト SSH 経由でコマンドを実行する対象サーバー
ローカルシェル ローカルマシン上でコマンドを実行する環境

コンテナ図

Runn コマンド実行 Go テストから呼び出し ユーザー CLI Go パッケージ API オーケストレーター ステートストア ランナー層
要素名 説明
CLI run / list / new / coverage 等のサブコマンドを提供するコマンドラインインターフェース
Go パッケージ API runn.Load() / runn.New() / runn.Run() 等を提供する Go ライブラリ
オーケストレーター Runbook を解析し、ステップを順序制御して実行するエンジン
ステートストア ステップ間の変数・実行結果を保持する中央状態管理コンポーネント
ランナー層 各プロトコルへのリクエスト送信を担うプロトコルランナーの集合体

コンポーネント図

オーケストレーター ステートストア ランナー層 operator - 単一 Runbook 実行エンジン operatorN - 複数 Runbook 調整エンジン book - Runbook 設定パーサー store.Store vars 名前空間 steps 名前空間 needs 名前空間 env 名前空間 httpRunner grpcRunner dbRunner cdpRunner sshRunner execRunner testRunner includeRunner bindRunner dumpRunner
要素名 説明
operator 単一 Runbook のステップ順次実行・ランナー初期化・遅延ステップ管理を担う実行エンジン
operatorN 複数 Runbook の依存グラフ解決・トポロジカルソート・並列/逐次実行を担う調整エンジン
book YAML Runbook ファイルを解析し、ランナー定義・変数・ステップ設定を集約する設定パーサー
store.Store vars / steps / needs 等の名前空間を管理するステップ間共有の状態ストア
vars 名前空間 Runbook に定義した変数を保持するスコープ
steps 名前空間 各ステップの実行結果を保持するスコープ
needs 名前空間 依存 Runbook の実行結果を保持するスコープ
env 名前空間 OS 環境変数を保持するスコープ
httpRunner HTTP/REST サービスへのリクエスト実行。OpenAPI スキーマ検証対応
grpcRunner gRPC サービスへの Unary / Server streaming / Client streaming RPC 実行
dbRunner MySQL / PostgreSQL / SQLite3 / Cloud Spanner 等の SQL データベースへのクエリ実行
cdpRunner Chrome DevTools Protocol によるブラウザ操作
sshRunner SSH 経由でのリモートホスト上のコマンド実行
execRunner ローカルシェルでのコマンド実行
testRunner expr-lang/expr によるアサーション式評価の組み込みランナー
includeRunner 別の Runbook を変数上書き付きで入れ子実行する組み込みランナー
bindRunner ステップ結果を変数にバインドする組み込みランナー
dumpRunner 変数・ステップ結果を出力・ロギングする組み込みランナー

データ

概念モデル

Runbook Runners Vars Secrets Steps HostRules Loop - Runbook Step Runner Call Loop - Step Bind Test Dump Include HTTP Runner gRPC Runner DB Runner SSH Runner CDP Runner Exec Runner Store vars namespace steps namespace needs namespace parent namespace env namespace current namespace previous namespace runn.kv namespace
要素名 説明
Runbook シナリオ定義ファイルの最上位単位
Runners ステップが利用するプロトコル別接続設定の集合
Vars ユーザー定義変数の集合
Secrets 出力時にマスクする機密値の一覧
Steps 順序付きステップの集合(リストまたは名前付きマップ)
HostRules ホスト名をリマップするルールの集合
Loop - Runbook Runbook 全体の繰り返し設定
Step 単一操作の実行単位
Runner Call Step が呼び出すプロトコル別実行
Loop - Step Step レベルの繰り返し・リトライ設定
Bind ステップ結果を変数に束縛する操作
Test ステップ結果を検証するアサーション
Dump 評価結果を出力する操作
Include 別の Runbook を入れ子で呼び出す操作
HTTP Runner HTTP/HTTPS エンドポイントへの接続設定
gRPC Runner gRPC エンドポイントへの接続設定
DB Runner データベースへの DSN ベースの接続設定
SSH Runner SSH リモートホストへの接続設定
CDP Runner Chrome DevTools Protocol ブラウザへの接続設定
Exec Runner ローカルシェルコマンドの実行設定
Store 実行中の状態を保持する中央ストア
vars namespace vars: で定義したユーザー変数の格納領域
steps namespace 各ステップの実行結果の格納領域
needs namespace 依存 Runbook の実行結果の格納領域
parent namespace 親 Runbook の変数の格納領域(Include 時のみ)
env namespace OS 環境変数の格納領域
current namespace 現在実行中ステップの結果の格納領域
previous namespace 直前ステップの結果の格納領域
runn.kv namespace 複数 Operator 間で共有するキー・バリューストア

情報モデル

Runbook string: desc: string_list: labels: string_list: needs: string: if: map: vars: string_list: secrets: duration: interval: Loop: loop: bool: skipTest: bool: force: bool: debug: bool: trace: map: hostRules: map: runners: Step_list: steps: Step string: desc: string: if: bool: defer: bool: force: Loop: loop: string: test: map: bind: any: dump: Include: include: Exec: exec: Loop int: count: string: until: duration: interval: duration: minInterval: duration: maxInterval: float: multiplier: float: jitter: Include string: path: map: vars: bool: skipTest: bool: force: HTTPRunner string: endpoint: string: openAPI3DocLocation: bool: skipValidateRequest: bool: skipValidateResponse: bool: useCookie: HTTPRequest string: path: string: method: map: headers: map: body: map: auth: GRPCRunner string: addr: bool: tls: string: cacert: string: cert: string: key: DBRunner string: dsn: DBStep string: query: string: exec: string: isolationLevel: SSHRunner string: host: string: user: string: identityFile: string: passphrase: CDPRunner string: addr: ExecRunner string: command: string: shell: string: stdin: map: env: Store map: vars: list_or_map: steps: map: needs: map: parent: map: env: any: current: any: previous: map: kv: int: i: steps 1 * loop 1 0..1 runners 1 0..* runners 1 0..* runners 1 0..* runners 1 0..* runners 1 0..* runners 1 0..* loop 1 0..1 include 1 0..1 HTTP call 1 0..1 DB call 1 0..1 exec call 1 0..1 uses 1 1
要素名 説明
Runbook シナリオ全体の設定を集約する最上位データ構造
Runbook.desc シナリオの説明文
Runbook.labels フィルタリング用タグの配列
Runbook.needs 実行前に完了が必要な Runbook 識別子の配列
Runbook.if Runbook 全体の条件付き実行式
Runbook.vars ユーザー定義変数のマップ
Runbook.secrets マスク対象の機密値キー一覧
Runbook.interval ステップ間の待機時間
Runbook.loop Runbook 全体の繰り返し設定
Runbook.skipTest test アサーションをスキップするフラグ
Runbook.force ステップ失敗時も続行するフラグ
Runbook.hostRules ホスト名リマップルールのマップ
Runbook.runners Runner 設定のマップ(キーはステップ内の呼び出し名)
Runbook.steps Step の配列またはキー付きマップ
Step 単一操作を定義するデータ構造
Step.if ステップの条件付き実行式
Step.defer LIFO 順で最後に実行するフラグ
Step.force このステップ失敗時も続行するフラグ
Step.loop ステップレベルの繰り返し設定
Step.test ステップ結果を検証するアサーション式
Step.bind 式の評価結果を変数名に束縛するマップ
Step.dump 評価結果を標準出力またはファイルに書き出す値
Step.include 別 Runbook を入れ子で呼び出す設定
Loop 繰り返し・リトライの設定データ構造
Loop.count 最大繰り返し回数(デフォルト 3)
Loop.until 繰り返しを終了する条件式
Loop.interval 繰り返し間の固定待機時間
Loop.minInterval 指数バックオフの最小待機時間
Loop.maxInterval 指数バックオフの最大待機時間
Loop.multiplier 指数バックオフの増加倍率(デフォルト 1.5)
Loop.jitter 待機時間のランダム変動量
Include 別 Runbook の参照設定
Include.path 参照する Runbook のファイルパスまたは URL
Include.vars 参照先 Runbook に渡す変数の上書きマップ
HTTPRunner HTTP エンドポイント設定
HTTPRunner.endpoint ベース URL
HTTPRunner.openAPI3DocLocation OpenAPI3 仕様ファイルのパスまたは URL
HTTPRequest HTTP ステップの呼び出し設定
HTTPRequest.path リクエストパス
HTTPRequest.method HTTP メソッド
HTTPRequest.headers リクエストヘッダーのマップ
HTTPRequest.body リクエストボディ(Content-Type 付きマップ)
GRPCRunner gRPC 接続設定
GRPCRunner.addr gRPC サーバーアドレス
GRPCRunner.tls TLS 有効フラグ
DBRunner データベース接続設定
DBRunner.dsn データベース接続 DSN 文字列
DBStep DB ステップの操作設定
DBStep.query SELECT 系クエリ文字列
DBStep.exec INSERT / UPDATE / DELETE 系クエリ文字列
DBStep.isolationLevel トランザクション分離レベル
SSHRunner SSH 接続設定
SSHRunner.host SSH ホスト名
SSHRunner.user SSH ユーザー名
SSHRunner.identityFile 秘密鍵ファイルパス
CDPRunner Chrome DevTools Protocol 接続設定
CDPRunner.addr CDP ブラウザのアドレス
ExecRunner ローカルコマンド実行設定
ExecRunner.command 実行するコマンド文字列
ExecRunner.shell 使用するシェル
Store 実行中の全状態を保持する中央データ構造
Store.vars ユーザー定義変数のマップ
Store.steps ステップ実行結果のリストまたはマップ
Store.needs 依存 Runbook の実行結果マップ
Store.parent 親 Runbook の変数マップ(Include 時のみ参照可能)
Store.env OS 環境変数のマップ
Store.current 現在実行中ステップの結果
Store.previous 直前ステップの結果
Store.kv Operator 間で共有するキー・バリューマップ
Store.i ループの現在インデックス(loop 実行中のみ有効)

構築方法

CLI ツールとしてインストール

方法 コマンド
Homebrew brew install k1LoW/tap/runn
aqua aqua g -i k1LoW/runn
go install go install github.com/k1LoW/runn/cmd/runn@latest
バイナリ直接 releases page からダウンロード
Docker 下記参照

Debian/Ubuntu(deb)

export RUNN_VERSION=X.X.X
curl -o runn.deb -L https://github.com/k1LoW/runn/releases/download/v$RUNN_VERSION/runn_$RUNN_VERSION-1_amd64.deb
dpkg -i runn.deb

RHEL/CentOS(RPM)

export RUNN_VERSION=X.X.X
yum install https://github.com/k1LoW/runn/releases/download/v$RUNN_VERSION/runn_$RUNN_VERSION-1_amd64.rpm

Alpine(apk)

export RUNN_VERSION=X.X.X
curl -o runn.apk -L https://github.com/k1LoW/runn/releases/download/v$RUNN_VERSION/runn_$RUNN_VERSION-1_amd64.apk
apk add runn.apk

Docker

docker container run -it --rm --name runn -v $PWD:/books ghcr.io/k1low/runn:latest list /books/*.yml

Go ライブラリとしてインストール

Go プロジェクトのテストヘルパーとして利用する場合は go get でインストールします。

go get github.com/k1LoW/runn

利用方法

CLI の主要コマンド

コマンド 用途
runn run ランブックの実行
runn list ランブック一覧の表示
runn new curl/grpcurl コマンドからランブックを生成
runn loadt 負荷テストモードでの実行
runn coverage カバレッジの分析

シナリオの生成と実行

runn new --and-run で curl コマンドからシナリオを自動生成して即時実行できます。

# HTTP シナリオを生成して実行
runn new --and-run --desc 'httpbin.org GET' --out http.yml -- curl https://httpbin.org/json -H "accept: application/json"

# gRPC シナリオを生成して実行
runn new --and-run --desc 'grpcb.in Call' --out grpc.yml -- grpcurl -d '{"greeting": "alice"}' grpcb.in:9001 hello.HelloService/SayHello

ランブックの一覧表示と実行

# ランブック一覧を表示
runn list path/to/**/*.yml

# 実行結果
  id:      desc:             if:       steps:  path
-------------------------------------------------------------------------
  a1b7b02  Only if included  included       2  p/t/only_if_included.yml
  85ccd5f  List projects.                   4  p/t/p/list.yml

# ランブックをまとめて実行
runn run path/to/**/*.yml

# 実行結果
S....
5 scenarios, 1 skipped, 0 failures

ランブックの基本構造

desc: シナリオの説明
runners:
  req: https://example.com       # HTTP ランナー
  db: mysql://user:pass@host/db  # DB ランナー
vars:
  username: alice
  password: ${TEST_PASS}         # 環境変数参照
steps:
  - desc: ステップの説明
    req:
      /users:
        post:
          headers:
            Authorization: 'Bearer xxxxx'
          body:
            application/json:
              username: "{{ vars.username }}"
    test: |
      current.res.status == 201

ステップはリスト形式(配列)とマップ形式(名前付き)の両方に対応しています。

ランナーの種類

runn は以下のランナーを提供しています。各ランナーの設定例は後続のサブセクションで説明します。

ランナー プロトコル 主な用途
httpRunner HTTP/HTTPS REST API テスト
grpcRunner gRPC RPC サービステスト
dbRunner SQL(MySQL/PostgreSQL 等) クエリ実行・検証
cdpRunner Chrome DevTools Protocol ブラウザ自動操作
sshRunner SSH リモートコマンド実行
execRunner ローカルシェル システムコマンド実行
includeRunner 入れ子ランブック テスト合成
testRunner 組み込み アサーション
dumpRunner 組み込み 標準出力/ファイル出力
bindRunner 組み込み 変数バインド
runnerRunner 動的 実行時ランナー生成

HTTP ランナーの設定例

runners:
  req: https://example.com
steps:
  - req:
      /users:
        post:
          headers:
            Authorization: 'Bearer xxxxx'
          body:
            application/json:
              username: alice
    test: |
      current.res.status == 201

gRPC ランナーの設定例

runners:
  greq:
    addr: grpc.example.com:8080
    tls: true
    cacert: path/to/cacert.pem
    cert: path/to/cert.pem
    key: path/to/key.pem
steps:
  - greq:
      grpctest.GrpcTestService/Hello:
        headers:
          authentication: tokenhello
        message:
          name: alice
          num: 3

DB ランナーの設定例

runners:
  db: postgres://dbuser:dbpass@hostname:5432/dbname
steps:
  - desc: ユーザー一覧を取得
    db:
      query: SELECT * FROM users;
      trace: false
    test: |
      len(current.rows) > 0

対応する DSN スキーマ:

データベース DSN 例
PostgreSQL postgres:// または pg://
MySQL mysql:// または my://
SQLite3 sqlite:///path/to/db または sq://db
Cloud Spanner spanner://project/instance/database または sp://

CDP ランナーの設定例

runners:
  cc: chrome://new
steps:
  - desc: ページ遷移してテキスト取得
    cc:
      actions:
        - navigate: https://pkg.go.dev/time
        - click: 'body > header > div.go-Header-inner > nav > div > ul > li:nth-child(2) > a'
        - waitVisible: 'body > footer'
        - text: 'h1'
    test: |
      current.text != ""

SSH ランナーの設定例

runners:
  sc: ssh://username@hostname:port
steps:
  - desc: リモートホスト名を取得
    sc:
      command: hostname
    test: |
      current.exit_code == 0

詳細な接続設定:

runners:
  sc:
    hostname: hostname
    user: username
    port: 22
    localForward: '33306:127.0.0.1:3306'

Exec ランナーの設定例

steps:
  - exec:
      command: echo "hello world"
      shell: bash
    test: |
      current.exit_code == 0
  - exec:
      command: grep hello
      stdin: '{{ steps[0].res.rawBody }}'

条件付き実行と bind・dump

steps:
  - desc: 条件付きステップ
    if: vars.env == "production"
    req:
      /health:
        get:
          body: null
  - desc: 結果を変数にバインド
    bind:
      user_id: steps[0].res.body.id
  - desc: 変数をダンプ
    dump: vars.user_id

テストアサーションの具体例

steps:
  - req:
      /users:
        get:
          body: null
    test: |
      current.res.status == 200
      && len(current.res.body.users) > 0
      && current.res.body.users[0].name == "alice"
      && current.res.headers["Content-Type"][0] == "application/json"

Go テストヘルパーとしての利用

Go のテストコードからランブック YAML を読み込んで実行できます。

func TestServer(t *testing.T) {
    ts := httptest.NewServer(myHandler)
    t.Cleanup(ts.Close)

    opts := []runn.Option{
        runn.T(t),
        runn.Runner("req", ts.URL),
        runn.DBRunner("db", dbConn),
    }
    o, err := runn.Load("testdata/**/*.yml", opts...)
    if err != nil {
        t.Fatal(err)
    }
    if err := o.RunN(ctx); err != nil {
        t.Fatal(err)
    }
}

主要なオプション関数:

関数 用途
runn.T(t) testing.T への失敗連携
runn.Runner(key, url) HTTP ランナーの登録
runn.DBRunner(key, db) DB ランナーの登録
runn.Book(path) ランブックファイルの指定
runn.New(opts...) 単一ランブックの作成
runn.Load(pattern, opts...) 複数ランブックの読み込み

負荷テストモード

runn loadt で並行実行による負荷テストを実施できます。

runn loadt --load-concurrent 10 path/to/**/*.yml

運用

実行制御オプション

フィルタリング

オプション 用途
--id ID で絞り込み --id a1b7b02
--label ラベルで絞り込み --label users --label auth
--match パターンで絞り込み --match "login"
$ runn run path/to/**/*.yml --label users --label projects
$ runn run path/to/**/*.yml --id a1b7b02

並列・分散実行

# 最大並列数を指定して実行
$ runn run --concurrent --max-concurrent 4 path/to/**/*.yml

# シャードで分散実行(CI の並列ジョブに有効)
$ runn run --shard 3/1 path/to/**/*.yml  # 3分割の1番目
$ runn run --shard 3/2 path/to/**/*.yml  # 3分割の2番目

その他の実行制御

# 最初のエラーで停止
$ runn run --fail-fast path/to/**/*.yml

# ランダム順序で実行(再現性のためシードを指定可)
$ runn run --shuffle --seed 12345 path/to/**/*.yml

# サンプリング実行
$ runn run --sample 5 path/to/**/*.yml

# テストアサーションをスキップして動作確認のみ
$ runn run --skip-test path/to/**/*.yml

環境変数

変数名 用途
RUNN_RUN ファイル名で Runbook をフィルタ
RUNN_SCOPES セキュリティスコープの有効化
$ env RUNN_RUN=login go test ./...
$ env RUNN_SCOPES=read:parent,read:remote runn run path/to/**/*.yml

スコープ管理

リスクのある操作はスコープで制御します。

スコープ 許可する操作
read:parent 作業ディレクトリ上位のファイル読み込み
read:remote リモートファイルの読み込み
run:exec Exec ランナーの実行
$ runn run path/to/**/*.yml --scopes read:parent,read:remote
$ runn run path/to/**/*.yml --scopes '!read:parent'  # 無効化

機密情報の保護

secrets に列挙した変数の値をログ出力でマスクします。

secrets:
  - vars.secret_token
  - binded_password
  - current.res.message.token

環境変数からシークレットを取り込めます。

vars:
  token: ${SECRET_TOKEN}

CI/CD 連携

GitHub Actions での利用

  • 単一バイナリのため外部依存なしで CI に組み込み可能
  • 終了コードでパイプラインの成否を伝達
  • --shard オプションで並列ジョブへの分散が可能
name: API Scenario Tests
on:
  push:
    branches: [main]
  pull_request:
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: ["2/1", "2/2"]
    steps:
      - uses: actions/checkout@v4
      - name: Install runn
        run: |
          brew install k1LoW/tap/runn
      - name: Run API tests
        run: |
          runn run --fail-fast --shard ${{ matrix.shard }} testdata/**/*.yml
      - name: Coverage report
        if: always()
        run: |
          runn run --coverage testdata/**/*.yml

カバレッジ収集

$ runn run --coverage path/to/**/*.yml

octocov-runn-coverage を使うと GitHub Actions でカバレッジを PR コメントに出力できます。

負荷テスト

loadt コマンド

$ runn loadt --load-concurrent 2 --max-rps 10 path/to/*.yml

Number of runbooks per RunN....: 15
Duration (--duration)..........: 10s
Concurrent (--load-concurrent).: 2
Max RunN per second (--max-rps): 10

Total..........................: 12
Succeeded......................: 12
Failed.........................: 0
Error rate.....................: 0%
RunN per seconds...............: 1.2
Latency .......................: max=1835ms min=1451ms avg=1627ms p90=1741ms p99=1788ms

閾値による合否判定

$ runn loadt --threshold 'error_rate < 10' path/to/*.yml
変数名 説明
total int 総実行数
succeeded int 成功数
failed int 失敗数
error_rate float エラー率(%)
rps float 毎秒実行数
max / min / avg float レイテンシ(ms)
p90 / p99 float パーセンタイル(ms)

プロファイリング

# 計測
$ runn run testdata/books/login.yml --profile

# 結果確認
$ runn rprof runn.prof
  runbook[login site](t/b/login.yml)           2995.72ms
    steps[0].req                                747.67ms
    steps[1].req                                185.69ms
    [total]                                    2995.84ms

デバッグ

デバッグモード

Runbook 内で有効化:

debug: true

CLI で有効化:

$ runn run --debug path/to/**/*.yml

実行内容のキャプチャ

実行内容をディレクトリに書き出して再現・分析できます。

$ runn run path/to/**/*.yml --capture path/to/dir

Go コードでの利用:

opts := []runn.Option{
    runn.T(t),
    runn.Capture(capture.Runbook("path/to/dir")),
}

トレース

HTTP リクエストに X-Runn-Trace ヘッダーを付与してトレースを伝播します。

trace: true

リトライ・ループ

ステップレベルのリトライ

steps:
  waitingroom:
    loop:
      count: 10
      until: 'steps.waitingroom.res.status == "201"'
      minInterval: 500ms
      maxInterval: 10
    req:
      /cart/in:
        post:
          body:
            application/json:
              item_id: "{{ vars.item_id }}"

Runbook レベルのループ

loop: 10
steps:
  - req:
      /items:
        get:
          body: null

並行制御

同一キーを持つ Runbook は排他的に実行されます。

concurrency: use-shared-db
concurrency:
  - use-shared-db
  - use-shared-api

ベストプラクティス

Runbook 設計

  • ステップには配列インデックスでなく名前付きキー(steps.<key>)を使用
  • クリーンアップ処理には defer: true を使い LIFO 順序で確実に実行
  • 複数 Runbook の連携は needs: で依存関係を明示
  • 共有状態には runn.kv を利用

環境切り替え

  • hostRules でエンドポイントを環境ごとに差し替え(コード変更不要)
runners:
  req: https://api.example.com
hostRules:
  - from: api.example.com
    to: staging.api.example.com
  • シークレットは vars に直書きせず環境変数(${VAR})で渡す

エラーハンドリング

  • デフォルトは最初のエラーで即時失敗
  • クリーンアップが必要なステップには force: true を設定
steps:
  cleanup:
    force: true
    dump: previous.res.body

トラブルシューティング

よくある問題と対処

症状 原因 対処
アサーション失敗 test: 式の評価エラー --debug で実行し変数値を確認
変数アクセスエラー 名前空間の誤り vars.* / steps[i].* / parent.* を確認
ランナー接続失敗 ホスト設定・TLS 設定の誤り hostRules と TLS 設定を確認
依存解決失敗 循環依存 needs: の依存グラフを確認(最大深度 10)
スコープエラー 許可されていない操作 --scopes で必要なスコープを追加

デバッグ手順

  1. --debug フラグで詳細ログを確認する
  2. --capture で実行内容をファイルに記録する
  3. --id で問題の Runbook を単体実行して絞り込む
  4. debug: true を Runbook に追加してステップ単位で確認する

まとめ

runn は、YAML ベースのランブックで HTTP / gRPC / DB / CDP / SSH 等のマルチプロトコルシナリオを記述し、CLI と Go ライブラリの両方から実行できる統合テスト・自動化ツールです。単一バイナリによる CI 組み込みの容易さと、OpenAPI 検証・式言語アサーション・負荷テスト・プロファイリングなどの充実した機能により、API シナリオテストから本番ワークフロー自動化まで幅広く活用できます。

本記事では、runn の概要から内部構造(C4 model での図解)、データモデル、各ランナーの設定方法、CI/CD 連携、運用ノウハウまでを体系的にまとめました。runn の導入を検討している方や、既存のシナリオテストの改善を考えている方の参考になれば幸いです。

この記事が少しでも参考になった、あるいは改善点などがあれば、ぜひリアクションやコメント、SNS でのシェアをいただけると励みになります!

参考リンク