はじめに
このドキュメントではテストツール Lux(LUcid eXpect scripting) の概要を紹介します。
Lux の概要
Lux は CLI ベースのシステムをテストするためのツールです。
Luxのテストスクリプトは主に send と expect というオペレーションで構成されています。
Luxは send で指定された文字列をシェルの stdin に送信し、expect で指定された文字列をシェルの stdout または stderr の出力とマッチングします。
全ての expect 行がマッチするとテストは SUCCESS と判断され、何れかの expect 行がマッチせずに timeoutした場合は FAIL と判断されます。timeout のデフォルトは 10秒です(変更可能)。文法ミスによってスクリプトが実行できない場合等は FAIL ではなく、ERROR と判断されます。
Lux はスクリプトのなかで複数のシェルを起動し、シェル間を行き来することができますが、アクティブなシェルは常にその中のひとつで、複数のシェルが同時にアクティブになることはありません。
基本的な文法
Symbol |
Description |
# |
# で始まる行はコメント。 |
! |
! で始まる行はSend。末尾に改行を含む。 |
~ |
~ で始まる行はSend。末尾に改行を含まない。 |
? |
? で始まる行はExpect。 マッチパタンには正規表現を使うことができる。 |
?? |
?? で始まる行はExpect。 正規表現を使わない場合はこちらを使用する。 |
- |
- で始まる行には失敗パタンを記述する。指定したパタンにマッチした場合、テストは即座に FAIL し、終了する。パタンは正規表現で記述できる。 |
+ |
+ で始まる行には成功パタンを記述する。指定したパタンにマッチした場合、テストは即座に SUCCESS し、終了する。パタンは正規表現で記述できる。 |
""" |
複数行にわたって Send, Expect 等の操作を行いたい場合は、対象を """ で囲む。実施したい操作は、開始側の """ の後の記号で指定する。
(例) 複数行に渡る正規表現のパタンマッチの場合、開始側は """?
|
[shell Name] |
"Name" というシェルをアクティブにする。 |
[cleanup] |
スクリプト終了後(正常、異常問わず)に実行したい処理を記述する。 テストの為に一時的に作成したファイルの削除等。 |
[global Var=Value] |
グローバル変数 "Var" を定義して値として "Value" をセットする。 グローバル変数は全てのシェルからアクセスできる。 |
[local Var=Value] |
ローカル変数 "Var" を定義して "Value" をセットする。 ローカル変数は変数が定義されたシェルからのみアクセスできる。 |
${Var} |
定義した変数は $Var もしくは ${Var} で参照することができる。 |
$${Var} |
Lux スクリプト内で定義した変数ではなく、システムの環境変数を参照したい場合は $$Var もしくは $${Var} を使う。 |
SH-PROMPT |
SH-PROMPT は Lux に事前定義されている変数でシステムのシェルプロンプトの変数である PS1 の値がセットされています。$ は付けずに使用します。 |
[timeout Seconds] |
指定した秒数の間にマッチする文字列を受信しなかった場合、テストを FAIL させる。デフォルトは 10秒。infinity を指定した場合、タイムアウトは無効。 |
[sleep Seconds] |
指定した秒数の間スリープする。 |
ここでは基本的な文法のみ記載しました。詳細は以下のドキュメントから確認してください。
https://github.com/hawk/lux/blob/master/doc/lux.md
Lux スクリプトの例
Lux のリポジトリには lux/examples 配下に幾つかサンプルスクリプトが含まれています。
以下は、lux/examples/intro.lux の内容です。
スクリプトは、シェルを 2つ起動して echo や cat コマンドの結果をテストした後、テスト中に生成した一時ファイルを削除して終了します。
[doc Test of single and multi line regular expressions]
# Assign a global variable which is accessible in all shells
[global file=removeme.txt]
# Start a shell
[shell single]
# Send text to the active shell
!echo foo
# Match output from the active shell
# The terminal echoes all input and here we match on the echoed input
?echo foo
# Start yet another shell (and make it the active one)
[shell multi]
# Create a file where bar and baz happens to be indented
# Variables are
!echo "foo" > $file
!echo " bar" >> $file
!echo " baz" >> $file
!echo "fum" >> $file
# Single line matches
!cat $file
?foo
?bar
# Don't bother of matching baz. All output between bar and fum is skipped.
?fum
# Match the predefined shell prompt
?SH-PROMPT:
# Multi line match. The first double quote char defines the first
# column of the regexp. The indentation of bar and baz is significant.
!cat $file
"""?
foo
bar
baz
fum
SH-PROMPT:
"""
# Switch back to the first shell
[shell single]
# Match the actual output from the echo command
?^foo
# Cleanup side effects. The cleanup section is always executed,
# regardless of the script succeeds or fails
[cleanup]
!rm -f $file
?SH-PROMPT:
# Match command exit status. Observe the double dollar sign which
# escapes the dollar sign, implying "echo ==$$?==" to be sent to
# the shell.
!echo ==$$?==
?^==0==
Lux スクリプトの実行例
lux examples/intro.lux
summary log : /Users/hmattsso/dev/lux/lux_logs/run_2017_08_23_11_45_14_493987/lux_summary.log
test case : examples/intro.lux
progress : ..:...:.:..:.:..:....:...:.:.:..:..:.:..:..:..:.:...:..:..:.:.:..:..:.:.:....c....:.:...:..:..:..:..:.:..:..:.
result : SUCCESS
successful : 1
summary : SUCCESS
file:///Users/hmattsso/dev/lux/lux_logs/run_2017_08_23_11_45_14_493987/lux_summary.log.html
.../lux> echo $?
0