第5章:ランナー詳細編 - 6大プロトコルを完全制覇!¶
ついに来た、runnの真骨頂! 他のテストツールが一つのプロトコルしか扱えない中、runnは6つのプロトコルを統一的に操る!この章では、各ランナーの秘伝の技を伝授しよう!
🎆 6大ランナー軍団 - あなたの最強の武器庫!¶
runnは6つの強力なランナーを搭載!それぞれが特定のプロトコルのスペシャリストだ!
ランナー | プロトコル | 用途 |
---|---|---|
🌐 HTTP | HTTP/HTTPS | REST API、GraphQL、Webhookを完全制圧! |
🔗 gRPC | gRPC | マイクロサービス間通信を爆速テスト! |
🗄️ DB | SQL | データベースを自在に操作! |
🌐 CDP | Chrome DevTools Protocol | ブラウザを完全支配! |
💻 SSH | SSH | リモートサーバーを思いのままに! |
⚙️ Exec | プロセス実行 | ローカルコマンドを瞬時に実行! |
🌐 HTTPランナー - Web APIテストの王者!¶
🚀 基本的な設定 - まずはここから始めよう!¶
desc: HTTPランナーの基本設定
runners:
api: https://api.example.com/v1
# 複数のエンドポイントを定義可能
auth: https://auth.example.com
webhook: http://localhost:8080/webhook
🎨 リクエストメソッドとパラメータ - あらゆるHTTPメソッドを制覇!¶
desc: HTTPリクエストメソッドとパラメータの例
runners:
httpbin: http://localhost:8080
steps:
# GET リクエスト
get_request:
httpbin:
/get?page=1&limit=10&sort=created_at:
get:
headers:
Accept: application/json
User-Agent: runn/test
test: |
current.res.status == 200 &&
current.res.body.args.page[0] == "1" &&
current.res.body.args.limit[0] == "10" &&
current.res.body.args.sort[0] == "created_at"
# POST リクエスト
post_request:
httpbin:
/post:
post:
headers:
Content-Type: application/json
body:
application/json:
name: "Alice"
email: "alice@example.com"
role: "user"
test: |
current.res.status == 200 &&
current.res.body.json.name == "Alice" &&
current.res.body.json.email == "alice@example.com" &&
current.res.body.json.role == "user"
# PUT リクエスト
put_request:
httpbin:
/put:
put:
body:
application/json:
name: "Alice Smith"
email: "alice.smith@example.com"
id: 123
test: |
current.res.status == 200 &&
current.res.body.json.name == "Alice Smith" &&
current.res.body.json.email == "alice.smith@example.com"
# PATCH リクエスト
patch_request:
httpbin:
/patch:
patch:
body:
application/json:
role: "admin"
test: |
current.res.status == 200 &&
current.res.body.json.role == "admin"
# DELETE リクエスト
delete_request:
httpbin:
/delete:
delete: {}
test: current.res.status == 200
# Bearer認証の例
auth_request:
httpbin:
/bearer:
get:
headers:
Authorization: "Bearer test-token-123"
test: |
current.res.status == 200 &&
current.res.body.authenticated == true &&
current.res.body.token == "test-token-123"
📦 様々なボディ形式 - どんなデータ形式もお手のもの!¶
desc: 様々なボディ形式のHTTPリクエスト
runners:
httpbin: http://localhost:8080
steps:
# JSON形式
json_request:
httpbin:
/post:
post:
body:
application/json:
key: "value"
nested:
array: [1, 2, 3]
test: |
current.res.status == 200 &&
current.res.body.headers["Content-Type"][0] == "application/json" &&
current.res.body.json.key == "value" &&
current.res.body.json.nested.array[0] == 1 &&
current.res.body.json.nested.array[1] == 2 &&
current.res.body.json.nested.array[2] == 3
# フォームデータ
form_request:
httpbin:
/post:
post:
body:
application/x-www-form-urlencoded:
username: alice
password: secret123
test: |
current.res.status == 200 &&
current.res.body.headers["Content-Type"][0] == "application/x-www-form-urlencoded" &&
current.res.body.form.username[0] == "alice" &&
current.res.body.form.password[0] == "secret123"
# マルチパートフォーム(テストデータ用の文字列フィールドのみ)
multipart_request:
httpbin:
/post:
post:
body:
multipart/form-data:
field1: "test value"
description: "Test multipart form"
test: |
current.res.status == 200 &&
current.res.body.headers["Content-Type"][0] contains "multipart/form-data" &&
current.res.body.form.field1[0] == "test value" &&
current.res.body.form.description[0] == "Test multipart form"
# プレーンテキスト
text_request:
httpbin:
/post:
post:
headers:
Content-Type: text/plain
body:
text/plain: |
This is a plain text message
with multiple lines
test: |
current.res.status == 200 &&
current.res.body.headers["Content-Type"][0] == "text/plain" &&
current.res.body.data contains "This is a plain text message" &&
current.res.body.data contains "with multiple lines"
# カスタムヘッダーとJSONボディ
custom_headers_request:
httpbin:
/anything:
put:
headers:
X-Custom-Header: "custom-value"
Authorization: "Bearer token123"
body:
application/json:
action: "update"
id: 42
test: |
current.res.status == 200 &&
current.res.body.method == "PUT" &&
current.res.body.headers["X-Custom-Header"][0] == "custom-value" &&
current.res.body.headers["Authorization"][0] == "Bearer token123" &&
current.res.body.json.action == "update" &&
current.res.body.json.id == 42
🔗 gRPCランナー - マイクロサービスの強い味方!¶
TODO: grpc の例を追加する
🗄️ データベースランナー - SQLの魔術師になれ!¶
🌍 対応データベース - あらゆるDBを制覇!¶
desc: 対応データベースの接続設定
runners:
# PostgreSQL
postgres: postgres://user:password@localhost:5432/testdb?sslmode=disable
# MySQL
mysql: mysql://user:password@localhost:3306/testdb
# SQLite
sqlite: sqlite:///path/to/database.db
# Cloud Spanner
spanner: spanner://projects/my-project/instances/my-instance/databases/my-db
📝 基本的なクエリ操作 - SQLを思いのままに!¶
desc: 基本的なデータベースクエリ操作
runners:
mydb:
dsn: sqlite:///tmp/db_basic_queries.db
trace: true
vars:
test_email: "test@example.com"
steps:
create_table:
mydb:
query: |
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
active BOOLEAN DEFAULT true,
password_hash TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
# INSERT クエリ
insert_user:
mydb:
query: |
INSERT INTO users (name, email, password_hash)
VALUES ('{{ faker.Username() }}', '{{ faker.Email() }}', '{{ toBase64(faker.Password(true, true, true, false, false, 12)) }}')
dump: current
test: |
current.last_insert_id == 1
# SELECT クエリ
select_users:
mydb:
query: |
SELECT id, name, email, created_at
FROM users
test: |
len(current.rows) <= 10
# UPDATE クエリ
update_user:
mydb:
query: |
UPDATE users
SET name = 'Updated name', updated_at = CURRENT_TIMESTAMP
WHERE id = {{ steps.insert_user.last_insert_id }}
dump: current
test: |
current.rows_affected == 1
# DELETE クエリ
delete_user:
mydb:
query: |
DELETE FROM users
WHERE id = {{ steps.insert_user.last_insert_id }}
test: current.rows_affected == 1
🌐 CDPランナー(ブラウザ自動化) - ブラウザを完全支配!¶
主なCDP actions一覧¶
アクション名 | 概要 |
---|---|
attributes | 要素の属性取得 |
click | 要素をクリック |
doubleClick | 要素をダブルクリック |
evaluate | JS式の評価 |
fullHTML | ページ全体のHTML取得 |
innerHTML | 要素のinnerHTML取得 |
localStorage | localStorage取得 |
location | 現在のURL取得 |
navigate | 指定URLへ遷移 |
outerHTML | 要素のouterHTML取得 |
screenshot | スクリーンショット取得 |
scroll | 要素までスクロール |
sendKeys | 要素にキー入力 |
sessionStorage | sessionStorage取得 |
setUploadFile | ファイルアップロード |
setUserAgent | User-Agent設定 |
submit | フォーム送信 |
tabTo | タブ切り替え |
text | 要素のテキスト取得 |
textContent | 要素のtextContent取得 |
title | ページタイトル取得 |
value | 要素のvalue取得 |
wait | 指定時間待機 |
waitReady | 要素の準備完了まで待機 |
waitVisible | 要素の表示まで待機 |
※詳細・最新情報は公式READMEをご参照ください。
🎮 基本的な使い方¶
desc: ブラウザ自動化テストの基本
runners:
cdp: chrome://new # 新しいChromeインスタンスを起動
steps:
# ページナビゲーション
navigate_to_page:
cdp:
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'
dump: current
test: |
current.text == 'Install the latest version of Go'
💻 SSHランナー - リモートサーバーの絶対的支配者!¶
🔑 基本的な設定 - サーバーへのセキュアアクセス!¶
desc: SSH経由でのリモート操作
runners:
server: ssh://user@example.com:22
# 秘密鍵を使用する場合
secure_server:
type: ssh
addr: user@secure.example.com:22
key: /path/to/private_key
passphrase: "{{ env.SSH_PASSPHRASE }}"
env:
SSH_PASSPHRASE: "${SSH_PASSPHRASE:-dummy-passphrase}"
steps:
# 基本的なコマンド実行
basic_command:
ssh:
server:///
command: ls -la /home/user
test: |
current.exit_code == 0 &&
current.stdout contains "total"
# 複数コマンドの実行
multiple_commands:
ssh:
server:///
command: |
cd /var/log
ls -la *.log | head -5
df -h
test: current.exit_code == 0
# ファイル操作
file_operations:
ssh:
server:///
command: |
echo "Test content" > /tmp/test.txt
cat /tmp/test.txt
rm /tmp/test.txt
test: |
current.exit_code == 0 &&
current.stdout contains "Test content"
# システム情報の取得
system_info:
ssh:
server:///
command: |
uname -a
uptime
free -m
ps aux | head -10
test: current.exit_code == 0
dump:
system_output: current.stdout
📏 サーバー監視とヘルスチェック - 24時間365日の番人!¶
desc: サーバー監視とヘルスチェック
runners:
server: ssh://user@example.com:22
steps:
health_check:
ssh:
server:///
command: |
# サービスの状態確認
systemctl is-active nginx
systemctl is-active postgresql
# ポートの確認
netstat -tlnp | grep :80
netstat -tlnp | grep :5432
# ディスク使用量
df -h | grep -E '(Filesystem|/dev/)'
# メモリ使用量
free -m
# CPU負荷
uptime
test: |
current.exit_code == 0 &&
current.stdout contains "active" &&
!(current.stdout contains "failed")
dump:
health_status: |
{
"services_active": current.stdout contains "active",
"ports_open": current.stdout contains ":80" && current.stdout contains ":5432",
"timestamp": time.now()
}
⚙️ Execランナー(ローカルコマンド実行) - シェルコマンドの魔術師!¶
🚀 基本的な使用方法 - コマンドを瞬時に実行!¶
desc: ローカルコマンドの実行
env:
PATH: "${PATH}"
steps:
# 基本的なコマンド実行
basic_exec:
exec:
command: echo "Hello, World!"
test: |
current.exit_code == 0 &&
current.stdout == "Hello, World!\n"
# 環境変数を設定してコマンド実行
exec_with_env:
exec:
command: env | grep TEST_VAR
env:
TEST_VAR: "test_value"
PATH: "{{ env.PATH }}"
test: |
current.exit_code == 0 &&
current.stdout contains "TEST_VAR=test_value"
# 作業ディレクトリを指定
exec_with_workdir:
exec:
command: pwd
dir: /tmp
test: current.stdout contains "/tmp"
# 複雑なシェルコマンド
complex_shell:
exec:
command: |
for i in {1..5}; do
echo "Count: $i"
done | grep "Count: [35]"
test: |
current.exit_code == 0 &&
current.stdout contains "Count: 3" &&
current.stdout contains "Count: 5"
📁 ファイル操作とテスト - ローカルファイルを完全管理!¶
desc: ファイル操作とテスト
steps:
# テストファイルの作成
create_test_file:
exec:
command: |
cat > /tmp/test_data.json << 'EOF'
{
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}
EOF
test: current.exit_code == 0
# ファイル内容の検証
validate_file:
exec:
command: cat /tmp/test_data.json
test: |
current.exit_code == 0 &&
fromJSON(current.stdout).users[0].name == "Alice"
# ファイルのクリーンアップ
cleanup:
exec:
command: rm -f /tmp/test_data.json
test: current.exit_code == 0
🎆 まとめ - ランナーマスター誕生!¶
やったぞ! あなたは今、6大ランナーを完全にマスターした!
🏆 この章で身につけた7つの必殺技:¶
- 🌐 HTTPランナー: REST API、GraphQL、認証フローを完全制圧!
- 🔗 gRPCランナー: マイクロサービス間通信を爆速テスト!
- 🗄️ DBランナー: データベースを思いのままに操作!
- 🌐 CDPランナー: ブラウザを完全自動化!
- 💻 SSHランナー: リモートサーバーを自由自在に監視!
- ⚙️ Execランナー: ローカルコマンドを瞬時に実行!
- 🌈 ランナーの組み合わせ: マルチプロトコルテストの達人に!
各ランナーを絶妙に組み合わせれば、どんなに複雑なシステムも完璧にテストできる。あなたはもう、プロトコルの支配者だ!