Test di unità degli script di bash

Abbiamo un sistema con alcuni script bash in esecuzione oltre al codice Java. Dal momento che stiamo provando a testare tutto ciò che potrebbe eventualmente rompere, e questi script di bash potrebbero rompersi, vogliamo testarli.

Il problema è che è difficile testare gli script di bash.

Esiste un modo o una best practice per testare gli script di bash? O dovremmo smettere di usare gli script di bash e cercare soluzioni alternative testabili?

In realtà esiste un framework di test delle unità per gli script di shell . Non l’ho usato da solo, ma potrebbe valerne la pena.

Domande simili sono già state poste prima:

  • Test unitario per script di shell
  • Prova tutto il protocollo negli script di shell

Ho ricevuto la seguente risposta da un gruppo di discussione:

è ansible importare (includere, qualunque sia) una procedura (funzione, qualunque sia il suo nome) da un file esterno. Questa è la chiave per scrivere uno script di test: dividi lo script in procedure indipendenti che possono essere importate sia nello script in esecuzione che nello script di test, e quindi il tuo script in esecuzione è il più semplice ansible.

Questo metodo è simile all’iniezione di dipendenza per gli script e sembra ragionevole. È preferibile evitare gli script di bash e usare un linguaggio più testabile e meno oscuro.

Test Bash compatibile con TAP : Bash Automated Testing System

racchetta-core

Perché dici che è “difficile” testare gli script di bash?

Cosa c’è di sbagliato con i wrapper di test come:

#!/bin/bash set -e errors=0 results=$($script_under_test $args<&1 let errors+=1 } echo "$results" | grep -q $expected1 || { echo "Test Failed. Expected $expected1" let errors+=1 } # and so on, et cetera, ad infinitum, ad nauseum [ "$errors" -gt 0 ] && { echo "There were $errors errors found" exit 1 } 

Epoxy è un framework di test Bash che ho progettato principalmente per testare altri software, ma lo uso anche per testare i moduli bash, inclusi se stesso e il cartone .

I principali vantaggi sono il sovraccarico di programmazione relativamente basso, l’annidamento illimitato delle asserzioni e la selezione flessibile delle asserzioni da verificare.

Ho fatto una presentazione confrontandola con BeakerLib , un framework usato da alcuni in Red Hat.

Prova bashtest . È un modo semplice per testare i tuoi script. Ad esempio, hai do-some-work.sh che cambia alcuni file di configurazione. Ad esempio, aggiungi nuova riga PASSWORD = 'XXXXX' nel file di configurazione /etc/my.cfg .

Scrivi i comandi bash riga per riga e poi controlla l’output.

Installare:

 pip3 install bashtest 

Creare test è un semplice comando di bash di scrittura.

File test-do-some-work.bashtest :

 # run the script $ ./do-some-work.sh > /dev/null # testing that the line "PASSWORD = 'XXXXX'" is in the file /etc/my.cfg $ grep -Fxq "PASSWORD = 'XXXXX'" /etc/my.cfg && echo "YES" YES 

Esegui test:

 bashtest *.bashtest 

Puoi trovare alcuni esempi qui e qui

Forse questo può essere usato, o contribuito a

https://thorsteinssonh.github.io/bash_test_tools/

Destinato a scrivere risultati nel protocollo TAP che immagino sia valido per CI, e buono per quelli che vogliono ambienti shell. Immagino che alcune cose siano eseguite in ambienti di shell, quindi alcuni potrebbero obiettare che dovrebbero essere testati nel loro ambiente di shell.

Fai un tentativo per assert.sh

 source "./assert.sh" local expected actual expected="Hello" actual="World!" assert_eq "$expected" "$actual" "not equivalent!" # => x Hello == World :: not equivalent! 

Spero che sia d’aiuto!

Nikita Sobolev ha scritto un eccellente post sul blog confrontando alcuni diversi framework di bash test: Test delle applicazioni Bash

Per gli impazienti: la conclusione di Nikita è stata quella di usare i pipistrelli ma sembra che Nikita abbia perso il progetto Bats-core che mi sembra essere quello da usare in avanti dato che il progetto originale di Bats non è stato mantenuto triggersmente dal 2013.

Mi piace molto shell2junit , una utility per generare output simile a JUnit dai test di script di Bash. Ciò è utile perché il report generato può essere letto da sistemi di integrazione continua, come i plug-in JUnit per Jenkins e Bamboo.

Mentre shell2junit non fornisce il completo framework di scripting di Bash come shunit2 , ti permette di avere una buona segnalazione dei risultati del test.

Potresti dare un’occhiata a bash_unit:

https://github.com/pgrange/bash_unit

Ho trovato difficile giustificare l’uso di bash per script più grandi quando Python ha enormi vantaggi:

  • Try / Except consente di scrivere script più robusti con la possibilità di annullare le modifiche in caso di errore.
  • Non è necessario utilizzare la syntax oscura come ‘ if [ x"$foo" = x"$bar"]; then ... if [ x"$foo" = x"$bar"]; then ... ‘che è incline agli errori.
  • Facile parsing di opzioni e argomenti usando il modulo getopt (e c’è un modulo ancora più semplice per analizzare gli argomenti, ma il nome mi sfugge).
  • Python ti permette di lavorare con liste / dict e oggetti invece di stringhe e array base.
  • Accesso a strumenti linguistici appropriati come regex, database (sicuro di poter colbind tutto al comando mysql in bash, ma non è il modo più bello di scrivere codice).
  • Non c’è bisogno di preoccuparsi di usare la forma corretta di $* o "$*" o "[email protected]" o $1 o "$1" , gli spazi nei nomi dei file non sono un problema, ecc. Ecc. Ecc.

Ora uso solo bash per il più semplice degli script.