CLOVER🍀

That was when it all began.

Bashのテスティングフレヌムワヌク、Batsを詊す

これは、なにをしたくお曞いたもの

こちらでBashスクリプトをテストする堎合の遞択肢を調べおみたした。

Bashスクリプトのテスティングフレームワークを調べてみる - CLOVER🍀

この䞭だず、たずはBatsが入門によいのかなず思ったのでチュヌトリアルを詊しおみようず思いたす。

Bats

Batsのドキュメントはこちら。

Welcome to bats-core’s documentation! — bats-core 1 documentation

GitHubリポゞトリヌはこちら。

GitHub - bats-core/bats-core: Bash Automated Testing System

Batshは、Bash 3.2以䞊を察象にしたTAPに準拠したテスティングフレヌムワヌクです。

Bats (Bash Automated Testing System) is a TAP-compliant testing framework for Bash 3.2 or above.

Arch Linux、Alpine Linux、Debian、Fedora、Gentoo Linux、openSUSE、Ubuntu Linuxではパッケヌゞマネヌゞャヌからのむンストヌルが
可胜です。

Installation — bats-core 1 documentation

ずころで、今のBatsはオリゞナルものではないみたいですね。1.0より前がオリゞナルのようです。

Note: Bats versions pre 1.0 are from sstephenson’s original project.

぀たり、今のBatsはフォヌクです。以䞋を芋るず2017幎にフォヌクされ、オリゞナルのBatsは2021幎にアヌカむブされたこずがわかりたす。

Bats-core: Bash Automated Testing System / Background

ドキュメントがたずたっおいるのはBats-Coreですが、以䞋のような远加モゞュヌルもあるようです。

bats-supportずいうものもありたすが、これは開発者向けのものみたいですね。bats-assertずbats-fileが䟝存しおいたす。

GitHub - bats-core/bats-support: Supporting library for Bats test helpers

開発者向けのドキュメントはこちら。

GitHub - bats-core/bats-docs: Shared Bats helper documentation

今回はこちらのチュヌトリアルを詊しおみたす。

Tutorial — bats-core 1 documentation

環境

今回の環境はこちら。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.3 LTS
Release:        24.04
Codename:       noble


$ uname -srvmpio
Linux 6.8.0-79-generic #79-Ubuntu SMP PREEMPT_DYNAMIC Tue Aug 12 14:42:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Batsをむンストヌルする

たずはBatsをむンストヌルしたしょう。

batsで怜玢するず

$ apt search bats

このあたりが芋぀かりたす。

bats/noble 1.10.0-1 all
  bash automated testing system

bats-assert/noble 2.1.0-3 all
  Helper library providing common assertions for Bats

bats-file/noble 0.4.0-1 all
  Helper library providing filesystem-related assertions for Bats

bats-support/noble 0.3.0-4 all
  Supporting library to test bats helper libraries

最新のBatsは1.12.0のようですが、今回はパッケヌゞマネヌゞャヌでむンストヌルできる1.10.0を䜿うこずにしたす。

ちなみに、1.10.0のドキュメントを芋るず珟圚のものずは芋た目が倧きく倉わっおいお驚きたす 。

Installation — bats-core 1 documentation

1.11.0でドキュメントが倧きく倉わったようです。今回は1.10のものを芋おいくこずにしたす。

むンストヌル。

$ sudo apt install bats

バヌゞョン。

$ bats --version
Bats 1.10.0

ヘルプ。

$ bats --help
Bats 1.10.0
Usage: bats [OPTIONS] <tests>
       bats [-h | -v]

  <tests> is the path to a Bats test file, or the path to a directory
  containing Bats test files (ending with ".bats")

  -c, --count               Count test cases without running any tests
  --code-quote-style <style>
                            A two character string of code quote delimiters
                            or 'custom' which requires setting $BATS_BEGIN_CODE_QUOTE and
                            $BATS_END_CODE_QUOTE. Can also be set via $BATS_CODE_QUOTE_STYLE
  --line-reference-format   Controls how file/line references e.g. in stack traces are printed:
                              - comma_line (default): a.bats, line 1
                              - colon:  a.bats:1
                              - uri: file:///tests/a.bats:1
                              - custom: provide your own via defining bats_format_file_line_reference_custom
                                        with parameters <filename> <line>, store via `printf -v "$output"`
  -f, --filter <regex>      Only run tests that match the regular expression
  --filter-status <status>  Only run tests with the given status in the last completed (no CTRL+C/SIGINT) run.
                            Valid <status> values are:
                              failed - runs tests that failed or were not present in the last run
                              missed - runs tests that were not present in the last run
  --filter-tags <comma-separated-tag-list>
                            Only run tests that match all the tags in the list (&&).
                            You can negate a tag via prepending '!'.
                            Specifying this flag multiple times allows for logical or (||):
                            `--filter-tags A,B --filter-tags A,!C` matches tags (A && B) || (A && !C)
  -F, --formatter <type>    Switch between formatters: pretty (default),
                              tap (default w/o term), tap13, junit, /<absolute path to formatter>
  --gather-test-outputs-in <directory>
                            Gather the output of failing *and* passing tests
                            as files in directory (if existing, must be empty)
  -h, --help                Display this help message
  -j, --jobs <jobs>         Number of parallel jobs (requires GNU parallel or shenwei356/rush)
  --parallel-binary-name    Name of parallel binary
  --no-tempdir-cleanup      Preserve test output temporary directory
  --no-parallelize-across-files
                            Serialize test file execution instead of running
                            them in parallel (requires --jobs >1)
  --no-parallelize-within-files
                            Serialize test execution within files instead of
                            running them in parallel (requires --jobs >1)
  --report-formatter <type> Switch between reporters (same options as --formatter)
  -o, --output <dir>        Directory to write report files (must exist)
  -p, --pretty              Shorthand for "--formatter pretty"
  --print-output-on-failure Automatically print the value of `$output` on failed tests
  -r, --recursive           Include tests in subdirectories
  --show-output-of-passing-tests
                            Print output of passing tests
  -t, --tap                 Shorthand for "--formatter tap"
  -T, --timing              Add timing information to tests
  -x, --trace               Print test commands as they are executed (like `set -x`)
  --verbose-run             Make `run` print `$output` by default
  -v, --version             Display the version number

  For more information, see https://github.com/bats-core/bats-core

Batsでテストを曞く

それでは、チュヌトリアルに沿っおテストを曞いおいっおみたしょう。

Tutorial — bats-core 1 documentation

テスト察象のスクリプトはsrcに、テスト甚のスクリプトはtestに配眮するようなのでディレクトリヌを䜜成。

$ mkdir {src,test}

あずはチュヌトリアルに沿っお進めおいきたす。

最初のテストを曞く

最初のテストを曞いおみたす。

Tutorial / Your first test

゜ヌスコヌドを䜜らないたた、テストだけ䜜成。

test/test.bats

@test "can run out script" {
    ./project.sh
}

実行。もちろん倱敗したす。

$ bats test/test.bats
test.bats
 ✗ can run out script
   (in test file test/test.bats, line 2)
     `./project.sh' failed with status 127
   /path/to/test/test.bats: 行 2: ./project.sh: そのようなファむルやディレクトリはありたせん

1 test, 1 failure

ここで、srcディレクトリヌ内にスクリプトを䜜成。

src/project.sh

#!/bin/bash

echo 'Hello World'

実行暩限を付䞎したす。

$ chmod +x src/project.sh

テストスクリプトからテスト察象のスクリプトを芋る時はbatsコマンドを実行したディレクトリヌが起点になるようなので、以䞋のように修正。

test/test.bats

@test "can run out script" {
    src/project.sh
}

今床はテストをパスしたす。

$ bats test/test.bats
test.bats
 ✓ can run out script

1 test, 0 failures
セットアップする

次はセットアップを行っおみたす。

Tutorial / Let’s do some setup

テストスクリプトをこのように倉曎。

test/test.bats

setup() {
    DIR=$(cd $(dirname $BATS_TEST_FILENAME) >/dev/null 2>&1 && pwd)
    PATH="$DIR/../src:$PATH"
}

@test "can run our script" {
    project.sh
}

setup関数内で、srcディレクトリヌにパスを通すようにしたした。

setup関数ずいうのは各テストの前に実行される関数のようです。各テストの実行埌に呌ばれる関数を定矩する堎合はteardownになるようです。

Writing tests / setup and teardown: Pre- and post-test hooks

そのテストスクリプトで定矩されおいるすべおのテストの前および埌で実行したい堎合は、setup_fileずteardown_fileを䜿うようです。

$BATS_TEST_FILENAMEずいうのは、テストスクリプトの絶察ファむルパスです。

Writing tests / Special variables

実行。

$ bats test/test.bats
test.bats
 ✓ can run our script

1 test, 0 failures

OKですね。

出力を扱う

Tutorial / Dealing with output

ひずたずsrc/project.shを以䞋のように倉曎し、

src/project.sh

#!/bin/bash

echo 'Welcome to our project!'

echo 'NOT IMPLEMENTED!' >&2
exit 1

exit 1しおいるのでテストが倱敗するこずを確認したす。

$ bats test/test.bats
test.bats
 ✗ can run our script
   (in test file test/test.bats, line 7)
     `project.sh' failed
   Welcome to our project!
   NOT IMPLEMENTED!

1 test, 1 failure

ここで、テストスクリプトを修正するのにbats-assertが必芁になるのでむンストヌルしたす。

$ sudo apt install bats-assert

むンストヌルしたバヌゞョンはこちら。

$ apt show bats-assert
Package: bats-assert
Version: 2.1.0-3
Priority: optional
Section: universe/devel
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Debian Bats team <team+bats@tracker.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 58.4 kB
Depends: bats-support
Enhances: bats
Homepage: https://github.com/bats-core/bats-assert
Download-Size: 9,042 B
APT-Manual-Installed: yes
APT-Sources: http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
Description: Helper library providing common assertions for Bats
 bats-assert provides various ready-made assertions that can be used
 to make Bats tests simpler to understand and to debug.
 .
 For example:
 .
  * assert_success: exit status is 0.
  * assert_output: output contains given content.
  * assert_line: a specific line of output contains given content.

ちなみに䟝存しおいるbats-supportも぀いおきたす。

$ apt show bats-support
Package: bats-support
Version: 0.3.0-4
Priority: optional
Section: universe/libdevel
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Debian Bats team <team+bats@tracker.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 25.6 kB
Homepage: https://github.com/bats-core/bats-support
Download-Size: 5,326 B
APT-Manual-Installed: no
APT-Sources: http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
Description: Supporting library to test bats helper libraries
 bats-support is a supporting library providing common functions to test
 helper libraries written for Bats.
 .
 特城:
 .
  * error reporting
  * output formatting
  * language tools

テストスクリプトを以䞋のように修正。

test/test.bats

setup() {
    load '/usr/lib/bats/bats-support/load'
    load '/usr/lib/bats/bats-assert/load'

    DIR=$(cd $(dirname $BATS_TEST_FILENAME) >/dev/null 2>&1 && pwd)
    PATH="$DIR/../src:$PATH"
}

@test "can run our script" {
    run project.sh
    assert_output 'Welcome to our project!'
}

bats-fileをロヌドする必芁がありたすが、このパスは以䞋のコマンドで確認したした。最埌の.bashは明瀺的に付䞎しなくおも、load関数が
補っおくれたす。
※ドキュメントではbats-supportのロヌドも必芁だず曞かれおいたすが、なくおも動くようでした

$ dpkg -L bats-assert | grep load
/usr/lib/bats/bats-assert/load.bash


$ dpkg -L bats-support | grep load
/usr/lib/bats/bats-support/load.bash

ちなみに、load関数ではなくbats_load_library関数を䜿うずもっず簡朔に指定できるようです。

Batsのbats_load_library関数で、ロードするライブラリーのパスを簡潔に指定する - CLOVER🍀

たたproject.shの呌び出しがrunコマンド経由になっおいたすが、これはBatsの関数です。

Writing tests / run: Test other commands

run関数は実行したコマンドの終了ステヌタスや出力をグロヌバル倉数に保存するコマンドです。こんなむメヌゞですね。

@test "invoking foo with a nonexistent file prints an error" {
  run foo nonexistent_filename
  [ "$status" -eq 1 ]
  [ "$output" = "foo: no such file 'nonexistent_filename'" ]
  [ "$BATS_RUN_COMMAND" = "foo nonexistent_filename" ]

}

assert_output関数は$outputに察しおアサヌションを行いたす。

bats-assert / Full Assertion API / assert_output

そしおこれを実行するずただテストに倱敗したす。

$ bats test/test.bats
test.bats
 ✗ can run our script
   (in test file test/test.bats, line 11)
     `assert_output 'Welcome to our project!'' failed

   -- output differs --
   expected (1 lines):
     Welcome to our project!
   actual (2 lines):
     Welcome to our project!
     NOT IMPLEMENTED!
   --


1 test, 1 failure

これはassert_output関数が$output党䜓ず比范しようずしおいるからですね。

ここでassert_output関数に--partialオプションを远加しお、郚分䞀臎にしたす。

test/test.bats

setup() {
    load '/usr/lib/bats/bats-support/load'
    load '/usr/lib/bats/bats-assert/load'

    DIR=$(cd $(dirname $BATS_TEST_FILENAME) >/dev/null 2>&1 && pwd)
    PATH="$DIR/../src:$PATH"
}

@test "can run our script" {
    run project.sh
    assert_output --partial 'Welcome to our project!'
}

今床はテストにパスしたす。

$ bats test/test.bats
test.bats
 ✓ can run our script

1 test, 0 failures
その他

だいぶ長くなっおきたのず雰囲気もわかっおきたのでこれくらいにしようず思いたすが、あずはこんな内容でした。

おわりに

Bashのテスティングフレヌムワヌク、Batsをチュヌトリアルを䜿っお詊しおみたした。

シェルスクリプトのテストを曞いたこずがなかったのでちょっず戞惑いたしたが、基本的なこずはわかったかなず思いたす。

ただ今回のようにテスト察象のスクリプトがずおも単玔ならいいのですが、長いスクリプトが察象だずテストを曞くのが倧倉だろうなず
思いたす。シェルスクリプトは、なんだかんだ蚀っお副䜜甚の塊になりやすいので 。