Testes na trilha de Bash

Aprenda a testar seus exercícios de Bash no Exercism


Você pode usar o editor online no site do Exercism para resolver os exercícios. Ou baixar os exercícios no seu computador, resolvê-los localmente e depois enviá-los para o Exercism. O restante deste documento fala sobre trabalhar localmente.

CLI do Exercism

Você vai precisar da ferramenta de linha de comando exercism para baixar e enviar exercícios. Veja a documentação da CLI do exercism.

Função wrapper para a ferramenta exercism

Um aspecto chato da ferramenta exercism padrão é que, depois de baixar um exercício, você precisa mudar de diretório manualmente. Esta função wrapper faz isso por você; guarde este código no seu ~/.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
}

Repare que isso não pode ser um script de shell, precisa ser uma função de shell. Scripts de shell são executados em um processo filho e não conseguem afetar o ambiente (como o diretório de trabalho atual) do seu shell atual.

Testando localmente

Para testar na trilha de bash, estamos usando o bats.

Rode os testes do exercício hipotético "whatever" assim:

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

Se você quiser imprimir a saída de depuração enquanto roda os testes localmente, veja Depuração local.

Instalando o bats-core

Você deve conseguir instalá-lo pelo seu gerenciador de pacotes favorito:

Para Mac (brew)

No macOS com o Homebrew, seria mais ou menos assim:

$ 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
  • O pacote bats legado também existe no ecossistema do homebrew. Não instale esse por engano: instale o bats-core.

Para Linux

Fedora 30 e mais recentes

O bats vem empacotado para o Fedora 30 e versões mais recentes; você pode instalá-lo com

sudo dnf install bats

Outras distribuições Linux

Para outras distribuições Linux, a implementação do bats que usamos pode não estar empacotada de forma conveniente. A melhor forma de instalá-la é a partir do código-fonte. Se você quiser instalá-la em /usr/local, então

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

Depois disso, supondo que /usr/local/bin esteja no seu $PATH, agora você pode fazer:

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

Para Windows (MINGW64/Cygwin)

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

Observação: se você estiver usando o desatualizado https://github.com/sstephenson/bats.git e encontrar um erro como cp: cannot create symbolic link '${HOME}/bin/bats': No such file or directory, você precisa copiar o conteúdo da pasta bin/bats/libexec/ para ${HOME}/bin/ manualmente.

Há relatos de que versões mais novas do bats não se comportam bem no bash do MinGW. Antes de rodar o script de instalação, talvez você queira:

$ git checkout v1.1.0

bats-assert

Para entender o significado dos vários comandos assert* nos testes, consulte a documentação da biblioteca bats-assert.

Testes ignorados

Resolver um exercício significa fazer com que todos os testes dele passem. Por padrão, apenas um teste (o primeiro) é executado quando você roda os testes. Isso é intencional, pois permite que você se concentre em fazer apenas esse teste passar. Depois que ele passar, você pode habilitar o próximo teste comentando ou removendo as

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

anotações que precedem os outros testes.

Sobrescrevendo os skips

Para rodar todos os testes, incluindo os que têm anotações skip, você pode definir a variável de ambiente BATS_RUN_SKIPPED com o valor true. Uma forma de definir isso apenas enquanto o bats executa é:

BATS_RUN_SKIPPED=true bats exercise_name.bats

Pode ser prático usar uma função wrapper para economizar digitação:

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

Aí é só rodar os testes com:

bats

bats legado

O bats-core nasceu de um fork da implementação original do bats. O projeto sstephenson/bats era bastante problemático e tinha sido abandonado. A propriedade foi transferida em 2017: sstephenson/bats#150 (comentário).

Se você tem o sstephenson/bats original instalado (verifique com bats -v; se ele indicar um número de versão menor que 1.0, é o caso), então você deve migrar para o bats-core; caso contrário, você pode acabar enfrentando falhas de teste sem explicação.