第3章:Expression文法編 - runnの真の力を解き放て!¶
🚀 expr-lang/expr - 最強の式評価エンジンとの出会い¶
ついに来た! runnの心臓部、expr-lang/exprの世界へようこそ!これは単なる式評価エンジンじゃない。テストシナリオに魔法をかける最強の相棒だ!
なぜexpr-lang/exprが最高なのか?¶
- ⚡ Go風の構文: Goプログラマーなら5秒で理解できる直感的な文法!
- 🛡️ 型安全: 実行時エラー?そんなものは過去の話だ!
- 🏃♂️ 爆速実行: コンパイル済み式でミリ秒単位の処理を実現!
- 🔒 完全サンドボックス: 安全な実行環境で何も心配いらない!
💪 基本的な式の構文 - これさえ覚えれば無敵!¶
🎯 リテラルと演算子 - あらゆるデータ型を自在に操れ!¶
expr-lang/exprでは、さまざまなリテラルと演算子を使って、データを表現することができる。以下の表は、リテラルの種類と例を示している。これらを駆使すれば、複雑なデータ構造も簡単に扱えるようになるよ! 詳しくは expr-lang Literals(リテラル) を参考にしてね!
種類 | 例 | 説明 |
---|---|---|
コメント | // コメント と /* コメント */ |
単一行コメント |
ブール値 | true 、false |
真偽値 |
整数 | 42 、-37 , 0x2A , 0o52 , 0b101010 |
整数値 |
浮動小数点数 | 0.5 、.5 |
小数値 |
文字列 | "Hello" 、'World' |
文字列(単一または二重引用符) |
配列 | [1, 2, 3] |
配列・リスト |
マップ | {a: 1, b: 2, c: 3} |
連想配列・オブジェクト |
nil | nil |
null値 |
steps:
literals_demo:
test: |
// 数値
42 == 42 &&
3.14 < 4 &&
// 文字列
"hello" + " world" == 'hello world' &&
// ブール値
true && !false &&
// 配列
[1, 2, 3][0] == 1 &&
len([1, 2, 3]) == 3 &&
// マップ
{"name": "alice", "age": 30}.name == "alice"
⚖️ 比較演算子 - 真偽を見極める審判の目!¶
steps:
comparison_demo:
test: |
// 基本的な比較
10 > 5 &&
"apple" < "banana" &&
100 >= 100 &&
50 <= 100 &&
// 等価性
"test" == "test" &&
100 != 99 &&
// 包含チェック
"running" contains "run" &&
2 in [1, 2, 3] &&
"key" in {"key": "value"}
🔥 変数参照の詳細 - データの海を自由に泳げ!¶
📊 利用可能な変数一覧 - 7つの強力な武器¶
変数名 | スコープ | 説明 |
---|---|---|
vars |
グローバル | Runbookで定義された変数 |
env |
グローバル | 環境変数 |
steps |
グローバル | すべてのステップの結果 |
current |
ステップ内 | 現在のステップの結果 |
previous |
ステップ内 | 直前のステップの結果 |
i |
ループ内 | ループのインデックス |
parent |
Include内 | 親Runbookの変数 |
💡 変数アクセスの実践例 - これが本物のパワーだ!¶
desc: 変数参照の包括的な例
vars:
baseURL: https://api.example.com
users:
- id: 1
name: Alice
- id: 2
name: Bob
runners:
blog: http://localhost:8080
steps:
# varsへのアクセス
access_vars:
dump: |
{
"url": vars.baseURL,
"firstUser": vars.users[0].name,
"userCount": len(vars.users)
}
# 環境変数へのアクセス
access_env:
test: |
env.HOME != "" &&
env.USER != ""
# ステップ結果へのアクセス(マップ形式)
make_request:
blog:
/users:
get: {}
test: current.res.status == 200
dump: current.res.body
# 前のステップの結果を参照
use_previous:
test: |
previous.res.status == 200 &&
len(steps.make_request.res.body) >= 0
🎨 高度な式パターン - プロフェッショナルへの道¶
🔀 条件式(三項演算子) - スマートな分岐処理の極意!¶
steps:
conditional_expr:
dump: |
// 三項演算子
vars.environment == "prod" ? "https://api.example.com" : "http://localhost:8080"
🔍 フィルタリングとマッピング - データ操作の魔術師になれ!¶
vars:
products:
- name: "iPhone"
price: 999
category: "electronics"
- name: "Book"
price: 20
category: "books"
- name: "MacBook"
price: 1999
category: "electronics"
steps:
filter_example:
dump: |
// 価格が100以上の商品をフィルタ
filter(vars.products, {.price >= 100})
test: |
// カテゴリが"electronics"の商品数をカウント
len(filter(vars.products, {.category == "electronics"})) == 2
map_example:
dump: |
// 商品名のリストを作成
map(vars.products, {.name})
test: |
// すべての商品の価格が0より大きいことを確認
all(vars.products, {.price > 0})
📦 配列・マップ操作 - コレクションを思いのままに!¶
vars:
numbers: [1, 2, 3, 4, 5]
person:
name: "Alice"
skills:
- "Go"
- "Python"
- "JavaScript"
steps:
array_operations:
test: |
// スライス操作
vars.numbers[1:3] == [2, 3] &&
vars.numbers[:2] == [1, 2] &&
vars.numbers[3:] == [4, 5] &&
// 要素の存在確認
3 in vars.numbers &&
!(10 in vars.numbers)
// 配列の結合(TODO: これは動かない)
// vars.numbers + [6, 7] == [1, 2, 3, 4, 5, 6, 7]
map_operations:
test: |
// ネストしたアクセス
vars.person.skills[0] == "Go" &&
len(vars.person.skills) == 3 &&
// キーの存在確認
"name" in vars.person &&
!("age" in vars.person)
💼 実践的な式の例 - 現場で使える最強テクニック!¶
🎯 APIレスポンスの検証 - 完璧な検証の極意¶
desc: 複雑なAPIレスポンスの検証
runners:
blog: http://localhost:8080
steps:
add_user:
blog:
/users:
post:
body:
application/json:
name: "John Doe"
email: "john@example.com"
get_users:
blog:
/users:
get:
query:
page: 1
limit: 10
test: |
// ステータスコードの確認
current.res.status == 200 &&
// レスポンスボディの構造確認
// "data" in current.res.body &&
// "pagination" in current.res.body &&
// データの検証
len(current.res.body) <= 10
// claude が以下のようなコードを生成するが実際には動かない
// all(current.res.body.data, {
// "id" in . &&
// "email" in . &&
// .id > 0
// }) &&
// ページネーションの検証
// current.res.body.pagination.page == 1 &&
// current.res.body.pagination.limit == 10
🔧 デバッグのテクニック - 問題解決のマスターになる!¶
🔍 dump機能の活用 - すべてを可視化せよ!¶
TBD
⚠️ よくあるパターンと落とし穴 - 達人への必修科目!¶
1. 💀 null/undefinedの扱い - 空の罠を回避せよ!¶
steps:
null_handling:
test: |
# nullチェック
current.res.body.optional_field != null &&
# デフォルト値の設定
(current.res.body.optional_field ?? "default") != "default" &&
# ネストしたnullチェック
current.res.body.user?.profile?.bio != null
2. 🔄 型変換 - データ型の壁を打ち破れ!¶
steps:
type_conversion:
test: |
# 文字列から数値への変換は自動では行われない
current.res.body.count == "10" && # 文字列として比較
int(current.res.body.count) == 10 # 数値として比較
3. 🚧 配列の境界チェック - 安全第一の鉄則!¶
steps:
safe_array_access:
test: |
# 配列が空でないことを確認してからアクセス
len(current.res.body.items) > 0 &&
current.res.body.items[0].name == "test"
🎊 まとめ - Expression文法マスターへの道¶
おめでとう! あなたは今、runnの式評価エンジンの達人への第一歩を踏み出した!
🏆 この章で手に入れた5つの武器:¶
- ⚡ 基本的な構文: リテラル、演算子、比較 - 基礎こそが最強の土台!
- 🔑 変数参照: vars、steps、current、previousなど - データへの完全アクセス権!
- 🎯 高度なパターン: フィルタリング、マッピング、条件式 - プロ級のテクニック!
- 💪 実践的な使用例: APIレスポンスの検証、動的リクエスト構築 - 現場で即戦力!
- 🔧 デバッグテクニック: dump機能の活用、段階的な構築 - 問題解決の秘訣!
expr-lang/exprの強力な機能により、どんなに複雑なテストシナリオもエレガントに記述できる。でも、これはまだ序章に過ぎない!