Question

Nous avons un système qui a quelques scripts bash en cours d'exécution en plus du code Java. Étant donné que nous essayons de tester tout ce qui pourrait briser, et les scripts bash peut briser, nous voulons les tester.

Le problème est qu'il est difficile de tester les scripts bash.

Y at-il une manière ou d'une meilleure pratique pour tester les scripts bash? Ou devrions-nous cesser d'utiliser des scripts bash et rechercher des solutions alternatives qui sont testables?

Était-ce utile?

La solution 2

Je suis la réponse suivante à partir d'un groupe de discussion:

  

il est possible d'importer (y compris,   quelle que soit) une procédure (fonction,   quel que soit son nom) d'un externe   fichier. C'est la clé de l'écriture d'un   script test: vous briser votre   script dans des procédures indépendantes   qui peut ensuite être importé dans les deux   votre script en cours d'exécution et vos tests   script, puis vous avez votre course   scénario soit aussi simple que possible.

Cette méthode est comme l'injection de dépendance pour les scripts, et semble raisonnable. Éviter les scripts bash et en utilisant un langage plus testables et moins obscure est préférable.

Autres conseils

Il est en fait un shunit2 , un cadre de test unitaire à base de xUnit pour les scripts shell Bourne base. Je ne l'ai pas utilisé moi-même, mais il pourrait être utile de vérifier.

Des questions similaires ont déjà été posées:

TAP test Bash compatibles avec la norme: Bash système automatisé de test

  

TAP, le test Tout protocole, est une simple interface à base de texte entre les modules de test dans un harnais de test. TAP a commencé la vie dans le cadre du harnais de test pour Perl mais il a maintenant des implémentations en C, C ++, Python, PHP, Perl, Java, JavaScript, et d'autres.

époxy est un framework de test Bash I pour tester principalement conçu d'autres logiciels, mais je l'utiliser pour tester modules bash ainsi, y compris lui-même et Carton .

Les principaux avantages sont les frais généraux relativement faible de codage, l'imbrication de l'affirmation illimitée et la sélection flexible des assertions pour vérifier.

J'ai fait un comparant BeakerLib -. un cadre utilisé par certains à Red Hat

Nikita Sobolev a écrit un excellent article de blog comparer quelques différents cadres de test bash: Test d'applications Bash

Pour les impatients: la conclusion de Nikita était d'utiliser Les chauves-souris mais il semble que Nikita Vous avez manqué le projet Bats-core qui me paraîtraient celui d'utiliser à l'avenir que le projet de chauves-souris d'origine n'a pas été activement maintenue depuis 2013.

Pourquoi dites-vous qu'il est « difficile » pour tester les scripts bash?

Qu'est-ce qui ne va pas avec des enveloppes de test comme:

 #!/bin/bash
 set -e
 errors=0
 results=$($script_under_test $args<<ENDTSTDATA
 # inputs
 # go
 # here
 #
 ENDTSTDATA
 )
 [ "$?" -ne 0 ] || {
     echo "Test returned error code $?" 2>&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
 }

Je shell2junit , un utilitaire pour générer une sortie semblable à JUnit à partir de tests de script Bash. Ceci est utile parce que le rapport généré peut alors être lu par les systèmes d'intégration continue, tels que les plug-ins JUnit pour Jenkins et Bamboo.

Alors que shell2junit ne fournit pas le cadre de script Bash complet comme shunit2 , il ne permet vous avez bien compte rendu des résultats des tests.

bashtest . It `s façon simple de tester vos scripts. Par exemple, vous avez do-some-work.sh qui modifie certains fichiers de configuration. Par exemple, ajouter une nouvelle ligne PASSWORD = 'XXXXX' au fichier de configuration /etc/my.cfg.

Vous écrivez ligne de commandes bash par ligne et vérifier la sortie.

Installer:

pip3 install bashtest

Créer des tests est une commande bash juste écriture.

test-do-some-work.bashtest du fichier:

# 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

Exécution de tests:

bashtest *.bashtest

Vous pouvez trouver quelques exemples ici et ici

Peut-être que cela peut être utilisé, ou contribué à

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

Destiné à écrire des résultats dans le protocole TAP que j'imagine est bon pour CI, et bon pour ceux qui veulent des environnements shell. J'imagine des choses exécuter dans un environnement shell donc, certains pourraient faire valoir devraient être testés dans leur environnement shell.

Donnez essayer de assert.sh

source "./assert.sh"

local expected actual
expected="Hello"
actual="World!"
assert_eq "$expected" "$actual" "not equivalent!"
# => x Hello == World :: not equivalent!

it helps!

Je ne peux pas croire que personne ne parle OSHT ! Il est compatible avec à la fois TAP et JUnit, il est shell pur (qui est, pas d'autres langues concernées), il fonctionne de façon autonome aussi, et il est simple et directe.

Test se présente comme suit (extraits tirés de la page du projet):

#!/bin/bash
. osht.sh

# Optionally, indicate number of tests to safeguard against abnormal exits
PLAN 13

# Comparing stuff
IS $(whoami) != root
var="foobar"
IS "$var" =~ foo
ISNT "$var" == foo

# test(1)-based tests
OK -f /etc/passwd
NOK -w /etc/passwd

# Running stuff
# Check exit code
RUNS true
NRUNS false

# Check stdio/stdout/stderr
RUNS echo -e 'foo\nbar\nbaz'
GREP bar
OGREP bar
NEGREP . # verify empty

# diff output
DIFF <<EOF
foo
bar
baz
EOF

# TODO and SKIP
TODO RUNS false
SKIP test $(uname -s) == Darwin

Une course simple:

$ bash test.sh
1..13
ok 1 - IS $(whoami) != root
ok 2 - IS "$var" =~ foo
ok 3 - ISNT "$var" == foo
ok 4 - OK -f /etc/passwd
ok 5 - NOK -w /etc/passwd
ok 6 - RUNS true
ok 7 - NRUNS false
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
ok 9 - GREP bar
ok 10 - OGREP bar
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
not ok 13 - TODO RUNS false # TODO Test Know to fail

Le dernier test montre comme « non ok », mais le code de sortie est 0 car il est un TODO. On peut définir verbeux ainsi:

$ OSHT_VERBOSE=1 bash test.sh # Or -v
1..13
# dcsobral \!= root
ok 1 - IS $(whoami) != root
# foobar =\~ foo
ok 2 - IS "$var" =~ foo
# \! foobar == foo
ok 3 - ISNT "$var" == foo
# test -f /etc/passwd
ok 4 - OK -f /etc/passwd
# test \! -w /etc/passwd
ok 5 - NOK -w /etc/passwd
# RUNNING: true
# STATUS: 0
# STDIO <<EOM
# EOM
ok 6 - RUNS true
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
ok 7 - NRUNS false
# RUNNING: echo -e foo\\nbar\\nbaz
# STATUS: 0
# STDIO <<EOM
# foo
# bar
# baz
# EOM
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
# grep -q bar
ok 9 - GREP bar
# grep -q bar
ok 10 - OGREP bar
# \! grep -q .
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
not ok 13 - TODO RUNS false # TODO Test Know to fail

Renommer pour utiliser une extension .t et le mettre dans un sous-répertoire t, et vous pouvez utiliser prove(1) (partie de Perl) pour l'exécuter:

$ prove
t/test.t .. ok
All tests successful.
Files=1, Tests=13,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.11 cusr  0.16 csys =  0.31 CPU)
Result: PASS

Set OSHT_JUNIT ou passer -j pour produire une sortie de JUnit. JUnit peut également être combiné avec prove(1).

Je l'ai utilisé cette bibliothèque à la fois des fonctions de test en se procurant leurs fichiers puis affirmations en cours d'exécution avec IS / OK et leurs négatifs, et les scripts en utilisant RUN / NRUN. Pour moi, ce cadre fournit le plus de gain pour le moins au-dessus.

shellspec parce que je voulais un outil facile à utiliser et un outil utile.

Il écrit par pur script shell POSIX. Il a testé avec de nombreux obus de plus que shunit2. Il a des fonctionnalités puissantes que les chauves-souris / chauve-souris-core.

Par exemple, le soutien bloc imbriqué, facile à se moquer / stub, facile à sauter / en attente, les tests paramétrés, numéro de la ligne d'assertion, exécuter par numéro de ligne, l'exécution en parallèle, l'exécution aléatoire, TAP / formatter JUnit, la couverture et l'intégration CI, profileur et etc.

Voir la démo sur la page du projet.

J'ai essayé beaucoup de solutions présentées ici, mais trouvé la plupart d'entre eux encombrant et difficile à utiliser, donc je construit mon propre cadre petit test: https://github.com/meonlol/t-bash

Il est juste un fichier dans le repo que vous pouvez simplement lancer directement, avec un ensemble de base de style JUnit affirme.

Je l'ai utilisé professionnellement dans plusieurs projets internes et nous avons pu faire nos scripts bash super stable et résistant à la régression.

Vous pouvez jeter un oeil à bash_unit:

https://github.com/pgrange/bash_unit

Jetez un oeil à Outthentic , il est simple, extensible par de nombreuses langues (Perl, Python, Ruby, Bash sur le choix) et multi-plateforme (Linux, Windows) cadre pour tester toutes les applications en ligne de commande.

Je l'ai trouvé difficile de justifier l'utilisation bash pour les scripts plus importants lorsque Python a ces énormes avantages:

  • try / except permet d'écrire des scripts plus robustes avec la possibilité d'annuler les modifications en cas d'erreur.
  • Vous ne devez pas utiliser la syntaxe obscure comme « if [ x"$foo" = x"$bar"]; then ... » qui est sujette à des erreurs.
  • analyse syntaxique facile des options et des arguments à l'aide du module getopt (et il y a un module encore plus facile pour l'analyse des arguments, mais le nom me échappe).
  • Python vous permet de travailler avec des listes / dicts et des objets au lieu de chaînes de base et des réseaux.
  • L'accès aux outils linguistiques appropriés tels que regex, bases de données (que vous pourriez tout tuyau dans la commande mysql en bash, mais ce n'est pas la plus belle façon d'écrire du code).
  • Pas besoin de se soucier de l'utilisation correcte de la forme $* ou "$*" ou "$@" ou $1 ou "$1", des espaces dans les noms de fichiers ne sont pas un problème, etc, etc, etc.

Maintenant, je n'utilise que bash pour le plus simple des scripts.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top