1. 序章

Bashは非常に便利で人気のあるスクリプト言語であり、考えられるユースケースが非常に多くあります。 言語自体が非常に普及しているという事実にもかかわらず、それをテストするという考えは、Javaのような言語ほど普及していません。 これにより、コストのかかるエラーが発生し、コードの信頼性が低下する可能性があります。

このチュートリアルでは、この状況を変更し、Batsフレームワークを使用してBashスクリプトをテストする方法を学習します。

2. 設定

2.1. コウモリのインストール

まず、Batsをインストールする必要があります。 いくつかの方法で実行できますが、最も簡単な方法を選択します。 必要なリポジトリをGitHubからプロジェクトにサブモジュールとして複製するだけです。

$ git init
$ git submodule add https://github.com/bats-core/bats-core.git test/bats
$ git submodule add https://github.com/bats-core/bats-support.git test/test_helper/bats-support
$ git submodule add https://github.com/bats-core/bats-assert.git test/test_helper/bats-assert
$ git submodule add https://github.com/bats-core/bats-assert.git test/test_helper/bats-files

2.2. テストするプロジェクトの作成

次に、テストするものが必要です。 それでは、文字列を連結する簡単なスクリプトを作成しましょう。

#!/usr/bin/env bash

concatenated="$1$2"
echo "$concatenated"
echo "$concatenated" > $3

exit 0

新しい文字列をコンソールに出力しますが、ファイルにも保存します。 ファイルは、スクリプトの3番目のパラメーターに応じて名前が付けられます。 この小さなプログラムをproject.shと呼び、srcディレクトリに配置しましょう。

2.3. テストスーツの構成

最後に、テストファイルを作成して設定する必要があります。 test ディレクトリを作成し、その中に空のtest.batsファイルを配置しましょう。 実際のテストを作成する前に、使用するすべてのBatsヘルパーをロードする必要があります。 さらに、 src ディレクトリをpath変数に追加して、テストの記述を簡素化します。

#!/usr/bin/env bash

setup() {
    load 'test_helper/bats-support/load'
    load 'test_helper/bats-assert/load'
    load 'test_helper/bats-file/load'
    DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )"
    PATH="$DIR/../src:$PATH"
}

3. 簡単なテスト

私たちが書くことができる最も基本的なテストは、スクリプトがエラーなしで実行されるかどうかをチェックします。今のところ、スクリプトの出力を無視し、スクリプトが完了したかどうかを知りたいだけです。

@test "should run script" {
    project.sh 'Hello ' 'Baeldung' '/tmp/output'
}

テストを実行するには、複製されたリポジトリからBatsライブラリを呼び出す必要があります。

$ ./test/bats/bin/bats test/test.bats
 ✓ should run script

1 tests, 0 failures, 0 skipped

4. スクリプトの出力をアサートする

bats-assertコンポーネントをsetupメソッドにロードしたため、提供されたヘルパーを使用して出力文字列にアサーションをすばやく書き込むことができます。 出力が提供された文字列と正確に一致するかどうかを確認するには、assert_outputヘルパーを使用する必要があります。

@test "should return concatenated strings" {
    run project.sh 'Hello ' 'Baeldung' '/tmp/output'

    assert_output 'Hello Baeldung'
}

多くの場合、出力は長く複雑であるため、1対1で比較することは実用的ではありません。 幸い、文字列の一部のみが一致するかどうかを確認できます。

assert_output --partial 'Baeldung'

最後に、出力が提供された文字列と一致しないかどうかを確認することもできます。

refute_output 'Hello World'

5. ファイルのアサート

5.1. 存在を主張する

このスクリプトは、連結された文字列をファイルに保存します。その機能をテストしたいと思います。 ありがたいことに、 bats-file コンポーネントは、ファイルの存在を主張するための便利なヘルパーを提供してくれます。 出力ファイルが存在するかどうかをチェックするテストを書いてみましょう。

@test "should create file" {
    run project.sh 'Hello ' 'Baeldung' '/tmp/output'

    assert_exist /tmp/output
}

5.2. 清掃

スクリプトを実行するたびに、出力ファイルが作成されます。 これにより、ディスク上に混乱を生じさせることから、テストを非決定論的にすることまで、さまざまな問題が発生する可能性があります。 幸い、簡単な解決策があります。各テストの後にすべての一時ファイルを削除する必要があります。 ただし、すべてのテストでそれを自分で実装する必要はありません。 代わりに、特別なteardown関数を使用できます。

teardown() {
    rm -f /tmp/output
}

各テストの後に、Batによって自動的に実行されます。 すべてのテストの後で一度だけ実行したい場合は、teardown_file関数を使用することもできます。

6. その他のアサーション

アサーションヘルパーは非常に便利ですが、機能にも制限があります。 それらを超える必要がある場合は、Bashで記述されたブール式をアサートできます。たとえば、出力ファイルが存在することはすでにアサートされていますが、正しい内容が含まれているかどうかは確認していません。 cat コマンドを使用して変数にロードし、条件式を使用してチェックすることで、これを実行しましょう。

@test "should write to file" {
    run project.sh 'Hello ' 'Baeldung' '/tmp/output'

    file_content=`cat /tmp/output`
    [ "$file_content" == 'Hello Baeldung' ]
}

7. テストをスキップする

テストを除外する必要がある場合があります。 まだ実装されていない機能のテストを書いたか、今のところ無視したいバグがあるかもしれません。 コメントアウトすることもできますが、それは単にそれを忘れる可能性を生み出し、あまりエレガントではありません。 代わりに、スキップヘルパーを使用して、テストを無視するようにマークします

@test "should write logs" {
    skip "Logs are not implemented yet"
    run project.sh 'Hello ' 'Baeldung' '/tmp/output'

    file_content=`cat /tmp/logs`
    [ "$file_content" == 'I logged something' ]
}

ここで、テストを実行すると、スキップされたテストに関する情報が得られます。

$ ./test/bats/bin/bats test/test.bats
 ✓ should run script
 ✓ should return concatenated strings
 ✓ should create file
 ✓ should write to file
 - should write logs (skipped: Logs are not implemented yet)

5 tests, 0 failures, 1 skipped

8. 何でもテスト

Bashは他のプログラムを実行し、それらが生成した結果を操作するために頻繁に使用されるため、Batはあらゆるものをテストするために効果的に使用できます。 プロジェクトでノードをバージョン12にインストールする必要があるとします。 node –version フラグで実行し、出力をアサートすることで確認できます。

@test "test node version" {
    run node --version

    assert_output --partial "v12"
}

返された文字列に「v12」が含まれていない場合だけでなく、 node がまったくインストールされていない場合も、テストは失敗します。

9. 概要

このチュートリアルでは、BashスクリプトをテストするためにBatsライブラリを使用する方法を学びました。 基本的なテストを作成し、ライブラリが提供するアサーションヘルパーを使用して、独自のアサーションを作成する方法を学びました。 ファイルの操作方法とテスト後のクリーンアップ方法を調査しました。 最後に、Bashスクリプト以上のものをテストする可能性を検討しました。