shellspecのREADME.mdの日本語版です。
英語と日本語両方メンテナンスするのが嫌なので、日本語版はなくてもいいかなーとも思っていたんですが、気の迷いで書いちゃいました。(でもリポジトリには入れない予定)
頑張って英語で書いて、それを自分で日本語化するとかいう、なんという無駄感
あ、 Table of Contents のリンクがおかしいけど面倒なので直さないっす。ページ内検索でもしてください。
shellspec
POSIX互換シェルスクリプト用のBDDベースのテスティングフレームワーク
シェルスクリプトをテストしましょう!
Table of Contents
イントロダクション
スペックファイル
Describe 'sample' # Example group block Describe 'bc command' add() { echo "$1 + $2" | bc; } Example 'perform addition' # Example block When call add 2 3 # Evaluation The output should eq 5 # Expectation End End Describe 'implemented by shell function' . ./mylib.sh # add() function defined Example 'perform addition' When call add 2 3 The output should eq 5 End End End
特徴
- POSIX互換シェルに対応 (dash、bash、ksh、busybox等)
- BDD スタイルのシンタックス
- シェルスクリプト言語の構文と互換性のあるスペックファイル
- 純粋なシェルスクリプト実装
- 最小限の依存関係 (僅かなPOSIX互換コマンドのみ使用)
- ネスト可能なグループとレキシカルスコープ風のスコープの提供
- Before / After フック
- Skip / Pending 機能
- モックとスタブ (一時的な関数のオーバーライド)
- 内存の簡易タスクランナー
- モダンなレポート (カラー対応, エラー行番号表示)
- 拡張可能なアーキテクチャ (カスタムマッチャー、カスタムフォーマッター等)
- shellspec は shellspec 自身でテスト
サポートシェル
dash
, bash
, ksh
, mksh
, pdksh
, zsh
, posh
, yash
, busybox (ash)
動作確認プラットフォーム
- Linux (ubuntu, debian, alpine)
- Windows 10 (WSL, cygwin, Git Bash)
- macOS Mojave
- Solaris 11
確認済み旧バージョン(このバージョン以降で動作するでしょう)
- ash 0.3.8 (debian 3.0)
- dash 0.5.3 (debian 4.0)
- busybox ash 1.1.3 (debian 4.0)
- bash 2.03 (debian 2.2)
- zsh 3.1.9 (debian 2.2)
- pdksh 5.2.14 (debian 2.2)
- mksh 28 (debian 4.0)
- ksh93 93q (debian 3.1)
- ksh88 0.5.11 (solaris 11)
- posh 0.3.14 (debian 3.1)
- yash 2.30 (debian 7)
依存関係
shellspec はシェルスクリプトによって実装されているので、そのため動作に 必要なものはシェルと僅かなPOSIX互換コマンドのみです。
現在使用している外部コマンド
date
, mkdir
, rm
, mv
(推奨: printf
, ps
, readlink
, time
)
チュートリアル
インストール
shellspec をダウンロードしてPATHにシンボリックリンクを作成するだけです
例
$ cd /SOME/WHERE/TO/INSTALL $ wget https://github.com/ko1nksm/shellspec/archive/{VERSION}.tar.gz $ tar xzvf shellspec-{VERSION}.tar.gz $ ln -s /SOME/WHERE/TO/INSTALL/shellspec-{VERSION}/shellspec /EXECUTABLE/PATH/ # (例 /EXECUTABLE/PATH/ = /usr/local/bin/, $HOME/bin/)
またはシンボリックリンクを作成するために shellspec
を作成します (もし readlink
がない場合)
$ cat<<'HERE'>/EXECUTABLE/PATH/shellspec #!/bin/sh exec /SOME/WHERE/TO/INSTALL/shellspec-{VERSION}/shellspec "$@" HERE $ chmod +x /EXECUTABLE/PATH/shellspec
入門
プロジェクトディレクトリを作成して shellspec --init
を実行します。
# プロジェクトディレクトリの作成 $ mkdir <your-project-directory> $ cd <your-project-directory> # 初期設定 $ shellspec --init create .shellspec create spec/spec_helper.sh # スペックファイルを作成します (好みのテキストエディタを使用できます) $ cat<<'HERE'>spec/hello_spec.sh Describe 'hello.sh' . lib/hello.sh Example 'hello' When call hello shellspec The output should equal 'Hello shellspec!' End End HERE # lib/hello.sh の作成 $ mkdir lib $ touch lib/hello.sh # 関数を実装していないため失敗します $ shellspec # hello 関数の作成 (好みのテキストエディタを使用できます) $ cat<<'HERE'>lib/hello.sh hello() { echo "Hello ${1}!" } HERE # 成功します $ shellspec
サンプル
sample directoryを参照、 shellspec ディレクトリで shellspec sample
で実行できます。
基本構造
これらのDSLで構造化された Example を記述できます。
DSL | 説明 |
---|---|
Describe | Example group ブロックを定義します。Example group はネスト可能です。 |
Context | Describe の別名です。 |
Example | Example ブロックを定義します。 この中にexampleを書きます。 |
Specify | Example の別名です。 |
End | Example group または Example ブロックの終了です。 |
Todo | 空の example と同じですが、ブロックではありません。実装予定を示すワンライナー構文です。 |
ネスト可能なグループとスコープ
スペックファイルは正当なシェルスクリプトの構文ですが、スコープや行番号を実装するために変換処理を行っています。
それぞれの example group ブロック と example ブロックはサブシェルに変換されます。 そのためブロックの中で行われた変更はブロックの外に影響を与えません。
つまりローカル変数とローカル関数をスペックファイルで実現しています。 これは構造化されたスペックを記述するのにとても便利です。
もしどのような変換が行われるのか興味がある場合は、 --translate
オプションを使用してください。
一時的なブロックのスキップ
Describe
, Context
, Example
, Specify
ブロックの頭に x
をつけて
xDescribe
, xContext
, xExample
, xSpecify
とすることで一時的にブロックの実行をスキップできます。
フック
example の前後に実行されるフックを定義できます。
DSL | 説明 |
---|---|
Before | example 実行前に呼ばれるフックを定義します。 |
After | example 実行後に呼ばれるフックを定義します。 |
モック と スタブ
現在、shellspec はモックやスタブのための特別な関数は提供していません。 しかしシェル関数を再定義することで既存のシェル関数や外部コマンドをオーバーライドできます。 これをモックやスタブとして代用することが出来ます。
Describe
, Context
, Example
, Specify
ブロックがサブシェルで実行されることを思い出してください。
ブロックを抜けた時、オーバーライドした関数は元に戻ります。
Example
example ブロックは、仕様を記述する場所です。 最大一つの Evaluation と 複数の Expectations から構成されます。
Evaluation
検証のためのアクションを定義します。それぞれの Example は 最大一つの Evaluation を記述できます。
When call echo hello world <- evaluation type ->
DSL | 説明 |
---|---|
When | evaluation を定義します。 |
evaluation type | 説明 |
---|---|
call | シェル関数または外部コマンドを実行します。 |
invoke | シェル関数または外部コマンドをサブシェルで実行します。 |
run | 外部コマンドを実行します。 |
通常は call
を使用することでしょう。 invoke
は call
に似ていますが、サブシェルで実行します。
invoke
は evaluation のみで関数をオーバーライドしたい 時と exit
をトラップしたい時に便利です。
Expectation
検証する内容を定義します。
DSL | 説明 |
---|---|
The | The ステートメントを定義します。 |
It | It ステートメントを定義します。 |
The ステートメント
これは一番基本的な Expectation です。検証対象(subject)が予想された値であるかを評価(Evaluate)します。
The output should equal 4 <- subject -> <- matcher -> <- expected value ->
modifier は 評価前に subject を加工します。
The line 2 of output should equal 4 <- modofier -> <- subject ->
modifier はつなげることが出来ます。
The word 1 of line 2 of output should equal 4 <- multiple modifier -> <- subject ->
modifier の最初の引数が数値の場合は、代わりに序数を使用することも出来ます。
The second line of output should equal 4 <- modofier -> <- subject ->
It ステートメント
It ステートメント は The ステートメント のシンタックスシュガーです。長い主語を避けるために使用できます。
注意: rspecとは違い、It
は Example
の別名ではありません。
以下の2つの文章は同じ意味です。
The word 1 of line 2 of output should equal 4
It should equal 4 the word 1 of line 2 of output
ランゲージチェイン
shellspec は chai.js に似たランゲージチェインをサポートします。
ランゲージチェインは可読性を上げるためだけのものです。 Expectation の実行には影響を与えません。
- a
- an
- as
- the
以下の2つの文章は同じ意味です。
The first word of second line of output should valid number
The first word of the second line of output should valid as a number
Subject
検証を行う対象です。
Subject (検証対象) | 説明 |
---|---|
output stdout |
Evaluation の標準出力を subject として使用します。 |
error stderr |
Evaluation の標準エラー出力を subject として使用します。 |
status exit status |
Evaluation の終了ステータスを subject として使用します。 |
funciton <NAME> |
関数実行の標準出力を subject として使用します。 |
path <PATH> file <PATH> dir <PATH> |
(別名を解決した) パスを subject として使用します。 |
value <VALUE> string <VALUE> |
指定した値を subject として使用します。 |
variable <NAME> |
指定した変数の値を subject として使用します。 |
Modifier
検証を行う対象を加工します。
Modifier | 説明 |
---|---|
line <NUMBER> |
subject の指定された行を subject として使用します。 |
lines | subject の行番号を subject として使用します。 |
word <NUMBER> |
subject の指定された単語を subject として使用します。 |
contents | ファイルの中身を subject として使用します。 (現在の subject はファイルパスであること) |
length | subject の長さを subject として使用します。 |
Matcher
検証を行う処理の内容です。
exit status (subjectは終了ステータスであることを想定)
Matcher | 説明 |
---|---|
be success | 終了ステータスは成功であること |
be failure | 終了ステータスは失敗であること |
stat (subjectはファイルパスであることを想定)
Matcher | 説明 |
---|---|
be exist | ファイルは存在していること |
be file | ファイルはファイルであること |
be directory | ファイルはディレクトリであること |
be empty | ファイルは空であること |
be symlink | ファイルはシンボリックリンクであること |
be pipe | ファイルはパイプであること |
be socket | ファイルはソケットであること |
be readable | ファイルは読み取り可能であること |
be writable | ファイルは書込み可能であること |
be executable | ファイルは実行可能であること |
be block_device | ファイルはブロックデバイスであること |
be charactor_device | ファイルはキャラクターデバイスであること |
has setgid | ファイルは setgid フラグを持っていること |
has setuid | ファイルは setuid フラグを持っていること |
valid
Matcher | 説明 |
---|---|
be valid number | subject は数字として正しいこと |
be valid funcname | subject は関数名として正しいこと |
variable (subject は変数名であることを想定)
Matcher | 説明 |
---|---|
be defined | 変数は定義されていること (set) |
be undefined | 変数は未定義であること (unset) |
be blank | 変数は空であること (unset または 空文字) |
be present | 変数は存在すること (空文字でない文字列) |
string
Matcher | 説明 |
---|---|
start with <STRING> |
subject は <STRING> で始まっていること |
end with <STRING> |
subject は <STRING> で終わっていること |
equal <STRING> |
subject は <STRING> と一致していること |
include <STRING> |
subject は <STRING> を含んでいること |
match <PATTERN> |
subject は <PATTERN> とマッチすること |
other
Matcher | 説明 |
---|---|
satisfy <FUNCTION> [ARGUMENTS...] |
subject <FUNCTION> を満たすこと |
Helper
DSL | 説明 |
---|---|
Set | 変数に値を代入します。 |
Unset | 変数を未定義にします。 |
Path File Dir |
パスの別名を定義します。 |
Debug | デバッグメッセージを出力します |
Path alias
読みやすさのために長いパスに短い名前を定義することが出来ます。
例
Example 'not use path alias' The file "/etc/hosts" should be exist End Example 'use path alias' File hosts="/etc/hosts" The file hosts should be exist End
Skip と Pending
現在実行しているブロックを Skip または Pending します。
DSL | 説明 |
---|---|
Skip <REASON> |
現在のブロックを Skip します。 |
Skip if <REASON> <FUNCTION> [ARGUMENTS...] |
現在のブロックを条件付きで Skip します。 |
Pending <REASON> |
現在のブロックを Pending します。 |
shellspec コマンド
デフォルトオプションの設定
shellspec
コマンドのデフォルトオプションを変更する場合は、オプションファイルを作成します。
以下の順番で読み込みを行い、オプションを上書きます。
$XDG_CONFIG_HOME/shellspec/options
$HOME/.shellspec
./.shellspec
./.shellspec-local
(VCSで管理しないでください)
タスクランナー
--task
オプションでタスクの実行を行います。
環境変数
Name | 説明 | 値 |
---|---|---|
SHELLSPEC_ROOT | shellspec ルートディレクトリ | 指定されていない場合は自動的判定します。(もし readlink がない場合は失敗するでしょう) |
SHELLSPEC_LIB | shellspec lib ディレクトリ | 指定されていない場合は $SHELLSPEC_ROOT/lib |
SHELLSPEC_LIBEXEC | shellspec libexec ディレクトリ | 指定されていない場合は $SHELLSPEC_ROOT/libexec |
SHELLSPEC_TMPDIR | shellspec が使用する一時ディレクトリ | 指定されていない場合は $TMPDIR or /tmp |
SHELLSPEC_SPECDIR | スペックファイルのディレクトリ | 現在のディレクトリ下の spec ディレクトリです |
SHELLSPEC_LOAD_PATH | ライブラリのロードパス | $SHELLSPEC_SPECDIR:$SHELLSPEC_LIB:$SHELLSPEC_LIB/formatters |
スペックディレクトリ以下の特殊ファイルとディレクトリ
spec/spec_helper.sh
spec_helper.sh は --require spec_helper
オプションでロードされます。
このファイルは example の実行のための準備を行います。(カスタムマッチャーの定義等)
spec/support/
このディレクトリはカスタムマッチャーやタスクファイルを作成に利用されます。
spec/banner
もし spec/banner
ファイルがある場合、shellspec
コマンド実行時にバナーを表示します。
バナー表示を無効にする場合は --no-banner
オプションを使用します。