第5章:ランナー詳細編¶
runnの特徴の一つは、複数のプロトコルを統一的に扱えることです。この章では、各ランナーの使い方を詳しく説明します。
runnが対応するランナー¶
runnは6つのランナーを提供しています。それぞれが特定のプロトコルに対応します。
ランナー | プロトコル | 用途 |
---|---|---|
HTTP | HTTP/HTTPS | REST API、GraphQL、Webhookのテスト |
gRPC | gRPC | マイクロサービス間通信のテスト |
DB | SQL | データベース操作のテスト |
CDP | Chrome DevTools Protocol | ブラウザ自動化 |
SSH | SSH | リモートサーバーの操作 |
Exec | プロセス実行 | ローカルコマンドの実行 |
HTTPランナー¶
基本的な設定¶
desc: HTTPランナーの基本設定
runners:
api: https://api.example.com/v1
# 複数のエンドポイントを定義可能
auth: https://auth.example.com
webhook: http://localhost:8080/webhook
リクエストメソッドとパラメータ¶
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 の例を追加する
データベースランナー¶
対応データベース¶
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
基本的なクエリ操作¶
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
steps:
# ホスト名を表示
show_hostname:
ssh:
server:///
command: hostname
test: current.exit_code == 0
dump: current.stdout
Execランナー(ローカルコマンド実行)¶
exec ランナーは、コマンドを実行します。
desc: ローカルコマンドの実行
steps:
# 基本的なコマンド実行
basic_exec:
exec:
command: echo "Hello, World!"
test: |
current.exit_code == 0 &&
current.stdout == "Hello, World!\n"