Bash 学习路径上的测试

了解如何在 Exercism 上测试你的 Bash 练习


你可以在 Exercism 网站上使用在线编辑器来解答练习。或者,把练习下载到自己的电脑上,在本地解答后再提交到 Exercism。本文档的其余部分讲的是如何在本地操作。

Exercism CLI

你需要用exercism命令行工具来下载和提交练习。参见 exercism cli 文档。

exercism 工具的包装函数

默认的 exercism 工具有个烦人的地方:下载练习后,你得手动切换目录。这个包装函数能帮你处理这件事;把它存到~/.bashrc里。

exercism () {
    local out
    readarray -t out < <(command exercism "$@")
    printf '%s\n' "${out[@]}"
    if [[ $1 == "download" && -d "${out[-1]}" ]]; then
        cd "${out[-1]}" || return 1
    fi
}

注意,它不能是 shell 脚本,必须是 shell 函数。Shell 脚本在子进程里执行,无法影响当前 shell 的环境(比如当前工作目录)。

在本地测试

bash 赛道上的测试使用的是 bats。

对于假设的“whatever”练习,可以像这样运行测试:

cd /path/to/your/exercise_workspace/bash/whatever
bats whatever.bats

如果你想在本地运行测试时打印调试输出,请参见 在本地调试。

安装bats-core

你应该可以从常用的包管理器里安装它:

在 Mac 上(brew)

在 macOS 上使用 Homebrew,大致是这样:

$ brew install bats-core
==> Downloading https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz
==> Downloading from https://codeload.github.com/bats-core/bats-core/tar.gz/v1.1.0
######################################################################## 100.0%
==> ./install.sh /usr/local/Cellar/bats-core/1.1.0
🍺  /usr/local/Cellar/bats-core/1.1.0: 13 files, 55KB, built in 4 seconds
  • 在 Homebrew 生态里还有旧的bats包。千万别装错:要安装bats-core。

在 Linux 上

Fedora 30 及更新版本

bats已经为 Fedora 30 及更新版本打包,可以用下面的命令安装:

sudo dnf install bats

其他 Linux

对于其他 Linux 发行版,我们所用的bats实现可能没有现成的软件包。最好的办法是从源码安装。如果你想把它装到/usr/local下,那就

git clone https://github.com/bats-core/bats-core
cd bats-core/
sudo ./install.sh /usr/local

之后,假设/usr/local/bin在你的 $PATH 里,现在就可以这样做:

$ bats
Error: Must specify at least one <test>
Usage: bats [-cr] [-f <regex>] [-j <jobs>] [-p | -t] <test>...
       bats [-h | -v]
...

在 Windows 上(MINGW64/Cygwin)

$ git clone https://github.com/bats-core/bats-core.git
$ cd bats-core
$ ./install.sh $HOME

注意:如果你用的是过时的https://github.com/sstephenson/bats.git,又遇到类似cp: cannot create symbolic link '${HOME}/bin/bats': No such file or directory这样的错误,那就得手动把bin/bats/libexec/文件夹里的内容复制到${HOME}/bin/。

有报告称较新的 bats 版本在 MinGW bash 上表现不佳,所以在运行安装脚本前,你可能想先:

$ git checkout v1.1.0

bats-assert

想了解测试里各种assert*命令的含义,请参考 bats-assert 库的文档。

跳过的测试

解答一道练习,意味着让它所有的测试都通过。默认情况下,运行测试时只会执行一个测试(第一个)。这是有意设计的,这样你就能专心先让那一个测试通过。一旦它通过,你就可以通过注释掉或删除下面这行,来启用下一个测试:

[[ $BATS_RUN_SKIPPED == true ]] || skip

这行注解加在其他测试的前面。

覆盖跳过

要运行所有测试(包括带skip注解的测试),你可以把环境变量BATS_RUN_SKIPPED的值设为true。一种只在运行 bats 期间设置它的方式是:

BATS_RUN_SKIPPED=true bats exercise_name.bats

用包装函数来省点打字会很方便:

bats() {
    BATS_RUN_SKIPPED=true command bats *.bats
}

之后只需这样运行测试:

bats

旧版bats

bats-core是从最初的bats实现分叉而来的。sstephenson/bats项目 bug 很多,而且已经被弃置了。项目所有权在 2017 年移交了出去:sstephenson/bats#150(评论)。

如果你装的是原本的 sstephenson/bats(可以用bats -v查看,如果报告的版本号低于 1.0),那就该换成 bats-core;否则你可能会遇到莫名其妙的测试失败。