Bats – profesjonalne testowanie skryptów Bash i aplikacji CLI w Linux

Skrypty Bash od lat są jednym z podstawowych narzędzi administratorów systemów Linux, inżynierów DevOps oraz programistów automatyzujących codzienne zadania. Ich popularność wynika z prostoty, dostępności i bardzo dobrej integracji z systemem operacyjnym.

Problem pojawia się wtedy, gdy skrypt zaczyna pełnić ważną rolę w infrastrukturze. Automatyczne wdrożenia, backupy, konfiguracja serwerów czy narzędzia CLI muszą działać przewidywalnie. Samo ręczne uruchamianie skryptu po każdej zmianie szybko przestaje być wystarczające.

W takich sytuacjach warto sięgnąć po Bats (Bash Automated Testing System) – lekki framework umożliwiający pisanie automatycznych testów dla skryptów Bash oraz dowolnych aplikacji uruchamianych z terminala.

Czym jest Bats?

Bats jest frameworkiem testowym dla powłoki Bash. Jego głównym założeniem jest możliwość testowania programu tak, jak zrobiłby to użytkownik:

użytkownik
    |
    v
terminal
    |
    v
aplikacja CLI
    |
    v
wynik działania

Test nie musi znać wewnętrznej implementacji programu. Nie interesuje go, czy aplikacja została napisana w Bash, Pythonie, Go czy Rust. Sprawdza jedynie publiczne zachowanie:

  • argumenty programu,
  • kod zakończenia,
  • komunikaty stdout/stderr,
  • wygenerowane pliki,
  • strukturę katalogów,
  • poprawność wyników.

To sprawia, że Bats doskonale nadaje się do testów typu black-box.

Instalacja Bats

Na większości dystrybucji Linux Bats można zainstalować przez menedżer pakietów.

Ubuntu / Debian

sudo apt install bats

Sprawdzenie instalacji:

bats --version

Alternatywnie można zainstalować najnowszą wersję z repozytorium:

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

Po instalacji polecenie:

bats

powinno być dostępne globalnie.

Pierwszy test w Bats

Załóżmy, że mamy prosty program:

#!/bin/bash

echo "Hello Linux"
exit 0

Zapisujemy go jako:

hello.sh

Następnie tworzymy katalog testów:

tests/
 └── hello_test.bats

Pierwszy test:

@test "Program zwraca poprawny komunikat" {
    run ./hello.sh

    [ "$status" -eq 0 ]
    [ "$output" = "Hello Linux" ]
}

Uruchomienie:

bats tests/

Rezultat:

1 test, 1 success

Bats automatycznie wykrywa wszystkie pliki zakończone rozszerzeniem .bats.

Biblioteki bats-support i bats-assert

Podstawowy Bats jest wystarczający do prostych przypadków, ale w większych projektach warto użyć dodatkowych bibliotek:

  • bats-support – dodaje pomocnicze funkcje testowe,
  • bats-assert – umożliwia czytelniejsze asercje.

Instalacja:

git clone https://github.com/bats-core/bats-support.git test/libs/bats-support

git clone https://github.com/bats-core/bats-assert.git test/libs/bats-assert

Struktura projektu:

project/
|
├── decoder
|
├── tests/
│   ├── libs/
│   │   ├── bats-support/
│   │   └── bats-assert/
│   |
│   └── decoder_test.bats

W pliku testowym importujemy biblioteki:

load 'libs/bats-support/load'
load 'libs/bats-assert/load'

Teraz możemy pisać bardziej czytelne testy:

@test "Decoder generuje plik CSV" {

    run ./decoder \
        --input sample.mf4 \
        --dbc vehicle.dbc \
        --output result.csv

    assert_success
    assert_output --partial "Decoding completed"

    [ -f result.csv ]
}

Zamiast:

[ "$status" -eq 0 ]

otrzymujemy:

assert_success

co jest znacznie łatwiejsze do zrozumienia.

Testowanie aplikacji CLI jako czarnej skrzynki

Załóżmy, że tworzymy narzędzie:

decoder \
 --dbc vehicle.dbc \
 --input recording.mf4 \
 --output data.csv

Test Bats może wyglądać tak:

@test "Dekodowanie poprawnego pliku MDF4" {

    run ./decoder \
        --dbc tests/data/car.dbc \
        --input tests/data/test.mf4 \
        --output "$BATS_TEST_TMPDIR/result.csv"

    assert_success

    assert_file_exist \
        "$BATS_TEST_TMPDIR/result.csv"
}

Test sprawdza cały przepływ:

  1. aplikacja startuje,
  2. argumenty są poprawne,
  3. plik MDF4 zostaje odczytany,
  4. dane są przetworzone,
  5. wynik zostaje zapisany.

Nie ma znaczenia, że wewnątrz działa Python, biblioteka cantools czy pandas.

Integracja z GitHub Actions

Jedną z największych zalet Bats jest łatwa integracja z CI/CD.

Przykładowy workflow:

name: Tests

on:
  push:
    branches:
      - main

jobs:
  bats:

    runs-on: ubuntu-latest

    steps:

    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Install Bats
      run: |
        sudo apt update
        sudo apt install bats

    - name: Run tests
      run: |
        bats tests/

Od tego momentu każdy commit będzie automatycznie sprawdzał poprawność aplikacji.

Porównanie wyników

W przypadku narzędzi generujących dane często stosuje się tak zwane golden files.

Przykład:

tests/
|
├── input/
│   └── sample.mf4
|
├── expected/
│   └── result.csv
|
└── decoder_test.bats

Test:

@test "Wynik dekodowania jest poprawny" {

    ./decoder \
       --input tests/input/sample.mf4 \
       --output result.csv

    diff \
       tests/expected/result.csv \
       result.csv
}

Jeżeli format wyjściowy się zmieni, test natychmiast wykryje różnicę.

Bats czy pytest, Go albo Rust?

Wybór zależy od celu.

Jeżeli testujemy bibliotekę lub kod wewnętrzny – framework języka aplikacji będzie lepszy.

Jeżeli testujemy publiczne API programu CLI – Bats jest bardzo dobrym rozwiązaniem.

Najważniejsze zalety:

CechaBats
Testowanie CLIbardzo dobre
Zależność od języka aplikacjibrak
Prostotabardzo wysoka
Linux/Unixidealne środowisko
CI/CDbardzo dobra integracja
Testy black-boxdoskonałe

Podsumowanie

Bats jest prostym, ale bardzo skutecznym narzędziem do automatyzacji testów w środowisku Linux. Szczególnie dobrze sprawdza się tam, gdzie aplikacja jest używana przez użytkownika jako polecenie terminalowe.

Dzięki podejściu black-box można testować rzeczywiste zachowanie programu bez uzależniania się od języka programowania, bibliotek czy struktury kodu.

Dla narzędzi CLI, skryptów administracyjnych i aplikacji DevOps Bats stanowi lekki odpowiednik dużych frameworków testowych, oferując jednocześnie prostotę typową dla świata Unix.

About the author

Autor "BIELI" to zapalony entuzjasta otwartego oprogramowania, który dzieli się swoją pasją na blogu poznajlinuxa.pl. Jego wpisy są skarbnicą wiedzy na temat Linuxa, programowania oraz najnowszych trendów w świecie technologii. Autor "BIELI" wierzy w siłę społeczności Open Source i zawsze stara się inspirować swoich czytelników do eksplorowania i eksperymentowania z kodem.