2009-08-27 26 views
78

Wir haben ein System, das einige Bash-Skripte neben Java-Code läuft. Da wir versuchen, alles zu testen, was möglicherweise brechen könnte, und diese Bash-Skripte könnten brechen, wollen wir sie testen.Unit Testing Bash-Skripte

Das Problem ist, es ist schwierig, Bash-Skripte zu testen.

Gibt es einen Weg oder eine Best Practice, um Bash-Skripte zu testen? Oder sollten wir aufhören, Bash-Skripte zu verwenden, und nach alternativen Lösungen suchen, die testbar sind?

+0

siehe auch: http://stackoverflow.com/questions/1315624/bash-and-test-driven-development –

+0

mögliches Duplikat von [Komponententests für Shell-Skripte] (http://stackoverflow.com/questions/971945/unit-testing-for-shell-scripts) – user

+0

Übersicht über die vorhandenen Tools: https://medium.com/wemake-services/testing-bash-applications-85512e7fe2de – sobolevn

Antwort

22

ich aus einer Diskussionsgruppe die folgende Antwort erhielt:

ist es möglich, importieren (enthalten, was auch immer) eine Prozedur (Funktion, wie auch immer es heißt) von einer externen Datei. Das ist der Schlüssel zu einem Testskript zu schreiben: Sie brechen Ihr Skript in unabhängige Verfahren , die dann sowohl in importiert werden können Ihre laufenden Skript und Ihre Tests Skript, und dann haben Sie Ihre laufenden Skript so einfach wie möglich .

Diese Methode ähnelt der Abhängigkeitsinjektion für Skripts und klingt vernünftig. Das Vermeiden von Bash-Skripten und das Verwenden von mehr testbaren und weniger obskuren Sprachen ist vorzuziehen.

+3

Ich bin nicht sicher, ob ich nach oben oder unten abstimmen sollte, auf der einen Seite Aufteilung in kleinere Teile ist gut, aber auf der zweiten Seite brauche ich ein Framework nicht eine Reihe von benutzerdefinierten Skripts – mpapis

+4

Wenn es darum geht, testen, imho, Modularität ist gut . – nimcap

+7

Während mit bash nichts falsch ist (ich habe viele, viele Skripte geschrieben), ist es eine harte Sprache zu meistern. Meine Faustregel ist, wenn ein Skript groß genug ist, um Tests zu benötigen, sollten Sie wahrscheinlich zu einer Skriptsprache wechseln, die leicht getestet werden kann. – Doug

36

Es gibt tatsächlich eine unit testing framework for shell scripts. Ich habe es nicht selbst benutzt, aber es könnte einen Besuch wert sein.

ähnliche Fragen gestellt wurden vor:

+2

Ich kann behaupten (Wortspiel beabsichtigt), dass shunit2 (Version 2.1 .6) ist bis jetzt ein bisschen kaputt. Die Funktionen assertNull und assertNotNull funktionieren nicht, auch wenn Sie ihnen direkte Werte zuführen. assertEquals funktioniert gut, aber ich denke, ich werde jetzt nur noch meine eigene machen müssen. – labyrinth

+0

@labyrinth, bist du sicher, dass das Problem nicht ein Fall davon war: https://github.com/kward/shunit2/issues/53 "Wie assertNull richtig verwenden?"? –

+0

@Victor Es ist definitiv möglich, dass ich mit meinen Anführungszeichen nicht vorsichtig genug war. Ich werde mich bald in eine Rolle zurückziehen, in der shunit2 oder irgendein Bash Unit-Testsystem sehr nützlich sein wird. Ich werde es erneut versuchen. – labyrinth

-4

Ich finde es schwer zu rechtfertigen bash für größere Skripte zu verwenden, wenn Python so große Vorteile:

  • Try/Except ermöglicht das Schreiben robusterer Skripts mit der Möglichkeit, Änderungen im Falle eines Fehlers rückgängig zu machen.
  • Sie müssen keine obskure Syntax wie 'if [ x"$foo" = x"$bar"]; then ...' verwenden, die fehleranfällig ist.
  • Einfache Analyse von Optionen und Argumenten mit dem Modul getopt (und es gibt ein noch einfacheres Modul zum Parsen von Argumenten, aber der Name entkommt mir).
  • In Python können Sie mit Listen/Dicts und Objekten statt mit einfachen Strings und Arrays arbeiten.
  • Zugang zu den richtigen Sprach-Tools wie Regex, Datenbanken (sicher, Sie könnten alles in den mysql Befehl in bash pipen, aber es ist nicht die schönste Art, Code zu schreiben).
  • Keine Notwendigkeit, über die Verwendung der richtigen Form von $* oder "$*" oder "[email protected]" oder $1 oder "$1", Leerzeichen in Dateinamen zu befürchten ist kein Problem, etc, etc, etc.

Jetzt habe ich nur bash verwenden für die einfachsten Skripte.

+3

Nicht zu leugnen, dass Python Vorteile hat, aber Ihr zweiter Punkt ist nicht sehr gut gestellt. Der gleiche Vergleich hätte als 'if [[$ foo = $ bar]]; dann ... '. Dies ist immer noch nicht besser als das, was Python zu bieten hat, aber es ist besser als das, was Sie präsentiert haben. –

+8

Einige Systeme (z. B. für eingebettete Systeme) haben kein Python zur Verfügung und Sie können keine zusätzlichen Daten installieren. –

+2

Ich persönlich liebe Bash, aber stimme zu, dass es ein wenig tückisch sein kann. In der Regel müssen Sie viel proaktiver sein, während Sie in Python * nach * Fehlern * nachgehen können. Allerdings hat bash 'trap' (um im Fehlerfall zu bereinigen/rückgängig zu machen) sowie regex (d. H.' [[$ 1 = ~^[1-3] {3} $]] '). Ich bin ziemlich sicher, dass die obskure Syntax, die Sie verwendeten, sich auf alte Implementierungen von 'test', nicht bash, bezieht. Bash eignet sich hervorragend für die Verbindung mit vorhandenen Befehlszeilentools ... Häufig ist eine einzelne Pipe zu "awk" oder "grep" viel einfacher als die Python-Alternative. – Six

6

Warum sagen Sie, dass es "hart" ist, Bash-Skripte zu testen?

Was mit Test-Wrapper falsch ist wie:

#!/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 
} 
+4

Erstens sind Bash-Skripte nicht gut lesbar. Zweitens sind die Erwartungen kompliziert, als ob geprüft wird, ob eine Sperrdatei mit der PID des Bash-Skripts erstellt wurde, das sie erstellt hat. – nimcap

+7

Noch wichtiger ist es, Shell-Skripte zu testen, da diese im Allgemeinen eine große Anzahl von Nebenwirkungen haben und Systemressourcen wie Dateisystem, Netzwerk usw. nutzen. Unit-Tests sind idealerweise nebenwirkungsfrei und nicht von Systemressourcen abhängig. – jayhendren

16
+11

Es lohnt sich zu enthüllen was TAP ist und warum sollte man sich kümmern, sonst ist es einfach sinnlos copy-paste –

+0

@ om-nom-nom: Ich habe es jetzt mit der TAP Seite verlinkt. –

+5

Da niemand sonst die unsayable sagte: TAP = Test Anything Protocol –

6

Epoxy ist ein Bash Test-Framework ich hauptsächlich zum Testen andere Software entworfen, aber ich benutze es bash-Module als auch zu testen, einschließlich itself und Carton.

Hauptvorteile sind relativ geringer Codierungsaufwand, unbegrenzte Assertion-Verschachtelung und flexible Auswahl der zu überprüfenden Assertionen.

Ich machte eine presentation im Vergleich zu BeakerLib - ein Framework von einigen bei Red Hat verwendet.

1

Ich mag shell2junit, ein Dienstprogramm, um JUnit-ähnliche Ausgabe von Bash-Skript-Tests zu generieren. Dies ist nützlich, da der erstellte Bericht dann von Systemen für die kontinuierliche Integration gelesen werden kann, z. B. den JUnit-Plug-Ins für Jenkins und Bamboo.

Während Shell2junit nicht die umfassende Bash-Scripting-Framework wie shunit2 bietet, ermöglicht es Ihnen eine schöne Berichterstattung über die Testergebnisse.

2

bashtest Versuchen. Es ist eine einfache Möglichkeit, Ihre Skripte zu testen. Zum Beispiel haben Sie do-some-work.sh, die einige Konfigurationsdateien ändern. Fügen Sie beispielsweise der Konfigurationsdatei /etc/my.cfg die neue Zeile PASSWORD = 'XXXXX' hinzu.

Sie schreiben Bash-Befehle Zeile für Zeile und überprüfen dann die Ausgabe.

Install:

pip3 install bashtest 

Tests erstellen ist ein einfach zu schreiben bash Befehle.

Datei 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 

Run Tests:

bashtest *.bashtest 

Sie some examples here und here

2

finden Vielleicht können diese verwendet werden, oder mitverursacht

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

Beabsichtigt, Ergebnisse in TAP-Protokoll zu schreiben, die ich für CI und gut für diejenigen, die Shell-Umgebungen wollen, gut vorstellen. Ich kann mir vorstellen, dass einige Dinge in Shell-Umgebungen laufen, daher sollten einige argumentieren, dass sie in ihrer Shell-Umgebung getestet werden sollten.

2

Geben Sie einen Versuch assert.sh

source "./assert.sh" 

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

Hoffe, es hilft!