यूनिट टेस्टिंग बैश स्क्रिप्ट


112

हमारे पास एक प्रणाली है जिसमें जावा कोड के अलावा कुछ बैश स्क्रिप्ट चल रही हैं। चूँकि हम हर उस चीज़ का परीक्षण करने की कोशिश कर रहे हैं जो संभवतः तोड़ सकती है, और जो बैश स्क्रिप्ट तोड़ सकती हैं, हम उन्हें परखना चाहते हैं।

समस्या यह है कि बैश स्क्रिप्ट का परीक्षण करना कठिन है।

क्या बैश स्क्रिप्ट का परीक्षण करने का एक तरीका या सर्वोत्तम अभ्यास है? या क्या हमें बैश स्क्रिप्ट का उपयोग करना छोड़ देना चाहिए और वैकल्पिक समाधानों की तलाश करनी चाहिए जो कि परीक्षण योग्य हो?




मौजूदा उपकरणों का अवलोकन: medium.com/wemake-services/...
sobolevn

जवाबों:


48

वास्तव में एक shunit2 है , Bourne आधारित शेल स्क्रिप्ट के लिए एक xUnit आधारित इकाई परीक्षण रूपरेखा है। मैंने स्वयं इसका उपयोग नहीं किया है, लेकिन यह जाँच के लायक हो सकता है।

इससे पहले भी इसी तरह के प्रश्न पूछे गए हैं:


3
मैं दावा कर सकता हूं (शंट का इरादा) कि shunit2 (संस्करण 2.1.6) आज तक थोड़ा टूट गया है। AssertNull और assertNotNull काम नहीं करते हैं, भले ही आप उन्हें सीधा मान खिलाएं। assertEquals ठीक काम करता है, लेकिन मुझे लगता है कि मैं अभी के लिए अपना रोल करने जा रहा हूं।
भूलभुलैया

@ लैब्रिंथ, क्या आपको यकीन है कि समस्या इस मामले में नहीं थी: github.com/kward/shunit2/issues/53 "एस्सरल का सही उपयोग कैसे करें?"
विक्टर सर्जेनको

1
@ विक्टर यह निश्चित रूप से संभव है कि मैं अपने दोहरे उद्धरणों के साथ पर्याप्त सावधान नहीं था। मैं जल्द ही एक भूमिका में वापस जा रहा हूं जहां shitit2 या कुछ बैश यूनिट-परीक्षण प्रणाली बहुत उपयोगी होगी। मैं इसे फिर से कोशिश करूँगा।
भूलभुलैया

5
मैं एक उपयोगकर्ता हूं और कभी-कभी shunit2 में योगदान देता हूं, और मैं पुष्टि कर सकता हूं कि परियोजना 2019 में जीवित और अच्छी तरह से है।
एलेक्स हार्वे

31

मुझे एक चर्चा समूह से निम्नलिखित उत्तर मिला:

बाहरी फ़ाइल से आयात करना (शामिल करना, जो भी हो) एक प्रक्रिया (कार्य, जो भी इसका नाम है)। यह एक परीक्षण स्क्रिप्ट लिखने की कुंजी है: आप अपनी स्क्रिप्ट को स्वतंत्र प्रक्रियाओं में तोड़ते हैं जो तब आपकी रनिंग स्क्रिप्ट और आपके परीक्षण स्क्रिप्ट दोनों में आयात किए जा सकते हैं, और फिर आपके पास अपनी रनिंग स्क्रिप्ट यथासंभव सरल होनी चाहिए।

यह विधि लिपियों के लिए निर्भरता इंजेक्शन की तरह है, और उचित लगता है। बैश स्क्रिप्ट से बचना और अधिक परीक्षण योग्य और कम अस्पष्ट भाषा का उपयोग करना बेहतर होता है।


4
मुझे यकीन नहीं है कि मुझे ऊपर या नीचे वोट करना चाहिए, एक तरफ छोटे भागों में विभाजित करना अच्छा है, लेकिन दूसरे हाथ पर मुझे कस्टम स्क्रिप्ट के एक सेट की रूपरेखा की आवश्यकता नहीं है
एमपीपीस

10
जबकि बैश में कुछ भी गलत नहीं है (मैंने कई, कई स्क्रिप्ट लिखी हैं), यह मास्टर करने के लिए एक कठिन भाषा है। मेरे अंगूठे का नियम यह है कि यदि कोई स्क्रिप्ट परीक्षण की आवश्यकता के लिए पर्याप्त है, तो आपको संभवतः एक स्क्रिप्टिंग भाषा पर आगे बढ़ना चाहिए जो आसानी से परीक्षण की जाती है।
डग

1
लेकिन कभी-कभी आपको कुछ ऐसा करने की आवश्यकता होती है जो उपयोगकर्ताओं के शेल में उपलब्ध हो सके। यह मेरे लिए स्पष्ट नहीं है कि आप शेल स्क्रिप्ट का सहारा लिए बिना कैसे करेंगे
इटकोवियन

@ इकोवियन - आप उदाहरण के लिए, रास्ते में एक निष्पादन योग्य निर्यात करने के लिए npm का उपयोग कर सकते हैं, इसलिए कोई सोर्सिंग आवश्यक नहीं है (आपके npm पैकेज को विश्व स्तर पर स्थापित करना होगा)
Eliran Malka

1
मैं बैश का उपयोग नहीं करने के बारे में सलाह का पालन करने जा रहा हूं। :)
मैकीज व्रजńसुक

30

TAP -compliant बैश परीक्षण: बैश स्वचालित परीक्षण प्रणाली

TAP, टेस्ट एनीथिंग प्रोटोकॉल, एक परीक्षण दोहन में परीक्षण मॉड्यूल के बीच एक सरल पाठ-आधारित इंटरफ़ेस है। TAP ने पर्ल के लिए परीक्षण दोहन के भाग के रूप में जीवन शुरू किया, लेकिन अब C, C ++, पायथन, PHP, पर्ल, जावा, जावास्क्रिप्ट और अन्य में कार्यान्वयन है।


14
यह बताने योग्य है कि TAP क्या है और इसकी देखभाल क्यों की जानी चाहिए, अन्यथा यह सिर्फ व्यर्थ कॉपी-पेस्ट है
om-nom-nom

@ om-nom-nom: मैंने इसे अब TAP साइट से जोड़ा।
Janus Troelsen

7
चूँकि कोई और नहीं कह रहा था, जो असंतुष्ट था: TAP = टेस्ट एनीथिंग प्रोटोकॉल
JW।

9

निकिता सोबोलेव ने कुछ अलग बैश टेस्ट फ्रेमवर्क की तुलना करते हुए एक उत्कृष्ट ब्लॉग पोस्ट लिखा: बैश एप्लिकेशन का परीक्षण

अधीर के लिए: निकिता का निष्कर्ष चमगादड़ का उपयोग करना था, लेकिन ऐसा प्रतीत होता है कि निकिता ने चमगादड़-कोर परियोजना को याद किया, जो मुझे आगे बढ़ने के लिए उपयोग करने के लिए प्रकट हुई क्योंकि मूल चमगादड़ परियोजना को 2013 से सक्रिय रूप से बनाए नहीं रखा गया है।


7

एपॉक्सी एक बैश टेस्ट फ्रेमवर्क है जिसे मैंने मुख्य रूप से अन्य सॉफ़्टवेयर के परीक्षण के लिए डिज़ाइन किया है, लेकिन मैं इसका उपयोग बैश मॉड्यूल के साथ-साथ स्वयं और कार्टन सहित परीक्षण करने के लिए भी करता हूं ।

मुख्य लाभ सत्यापित करने के लिए अपेक्षाकृत कम कोडिंग ओवरहेड, असीमित अभिकर्मक घोंसले और लचीले चयन हैं।

मैंने इसकी तुलना बीकेरलिब से करते हुए एक प्रस्तुति बनाई - रेड हैट में कुछ लोगों द्वारा इस्तेमाल किया गया एक ढांचा।


6

आप क्यों कहते हैं कि बैश स्क्रिप्ट का परीक्षण करना "कठिन" है?

टेस्ट रैपर के साथ क्या गलत है:

 #!/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
पहला, बैश स्क्रिप्ट बहुत पठनीय नहीं हैं। दूसरा, अपेक्षाएँ जाँचने की तरह जटिल होती हैं कि क्या कोई लॉक फ़ाइल बैश स्क्रिप्ट के PID के साथ बनाई गई है जिसने इसे बनाया है।
निकले

10
इससे भी महत्वपूर्ण बात यह है कि शेल स्क्रिप्ट का परीक्षण करना कठिन होता है क्योंकि उनमें आमतौर पर बड़ी संख्या में साइड इफेक्ट होते हैं और सिस्टम संसाधनों जैसे फाइल सिस्टम, नेटवर्क आदि का उपयोग करते हैं। आदर्श रूप से, यूनिट परीक्षण साइड-इफेक्ट मुक्त होते हैं और सिस्टम संसाधनों पर निर्भर नहीं होते हैं।
jayhendren

4

मैंने शेलस्पेक बनाया क्योंकि मैं एक आसान-से-उपयोग और उपयोगी उपकरण चाहता था।

यह शुद्ध POSIX खोल स्क्रिप्ट द्वारा लिखा गया है। इसने shunit2 से अधिक कई गोले के साथ परीक्षण किया है। इसमें चमगादड़ / चमगादड़-कोर की तुलना में शक्तिशाली विशेषताएं हैं।

उदाहरण के लिए, नेस्टेड ब्लॉक का समर्थन, मॉक / स्टब के लिए आसान, स्किप / लंबित, पैरामीटर किए गए परीक्षण, अभिकथन लाइन नंबर, लाइन नंबर द्वारा निष्पादित, समानांतर निष्पादन, यादृच्छिक निष्पादन, टैप / जनीत फॉर्मेटर, कवरेज और सीआई एकीकरण, प्रोफाइलर और आदि। ।

प्रोजेक्ट पृष्ठ पर डेमो देखें।


3

मुझे काफी शेल 2जनीट पसंद है , जो बैश स्क्रिप्ट परीक्षणों से जेनेट -जैसे आउटपुट उत्पन्न करने के लिए एक उपयोगिता है। यह उपयोगी है क्योंकि जनरेट की गई रिपोर्ट तब निरंतर एकीकरण प्रणालियों द्वारा पढ़ी जा सकती है, जैसे जेनकिन्स और बांस के लिए जेयूनाइट प्लग-इन।

Shell2junit की तरह व्यापक बैश पटकथा ढांचा उपलब्ध नहीं करता है shunit2 , यह आप परीक्षण के परिणाम की अच्छी रिपोर्टिंग की अनुमति नहीं है।


3

बैशटेस्ट की कोशिश करें । यह आपकी लिपियों का परीक्षण करने का सरल तरीका है। उदाहरण के लिए, आपके पास do-some-work.shकुछ कॉन्फिग फाइल को बदलना होगा। उदाहरण के लिए, PASSWORD = 'XXXXX'कॉन्फ़िग फ़ाइल में नई लाइन जोड़ें /etc/my.cfg

आप बैश कमांड लाइन को लाइन से लिखें और फिर आउटपुट चेक करें।

इंस्टॉल:

pip3 install bashtest

बनाएँ परीक्षण एक लिखने बैश कमांड है।

फ़ाइल 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

परीक्षण चलाएं:

bashtest *.bashtest

आप यहां और यहां कुछ उदाहरण पा सकते हैं


3

शायद इसका उपयोग किया जा सकता है, या इसमें योगदान दिया जा सकता है

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

TAP प्रोटोकॉल में परिणाम लिखने का इरादा है जो मुझे लगता है कि CI के लिए अच्छा है, और उन लोगों के लिए अच्छा है जो शेल वातावरण चाहते हैं। मुझे लगता है कि शेल वातावरण में कुछ चीजें चलती हैं, इसलिए हो सकता है कि कुछ लोग अपने शेल वातावरण में परीक्षण करें।


3

मुखर करने की कोशिश करो

source "./assert.sh"

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

आशा करता हूँ की ये काम करेगा!


3

मैं विश्वास नहीं कर सकता कि कोई भी OSHT के बारे में बात नहीं करता है ! यह TAP और JUnit दोनों के साथ संगत है , यह शुद्ध शेल है (जो कि कोई अन्य भाषा शामिल नहीं है), यह स्टैंडअलोन भी काम करता है, और यह सरल और प्रत्यक्ष है।

परीक्षण इस तरह दिखता है (परियोजना पृष्ठ से लिया गया स्निपेट):

#!/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

एक साधारण रन:

$ 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

अंतिम परीक्षण "ठीक नहीं" के रूप में दिखाता है, लेकिन निकास कोड 0 है क्योंकि यह ए है TODO। एक क्रिया को भी सेट कर सकते हैं:

$ 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

.tएक्सटेंशन का उपयोग करने के लिए इसे नाम दें और इसे एक tउपनिर्देशिका में डालें , और prove(1)इसे चलाने के लिए आप (पर्ल का हिस्सा) का उपयोग कर सकते हैं :

$ 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

JUnit आउटपुट तैयार करने के लिए सेट OSHT_JUNITया पास करें -j। JUnit को साथ भी जोड़ा जा सकता है prove(1)

मैंने इस लाइब्रेरी का उपयोग अपनी फ़ाइलों को सोर्स करने और IS/ OKऔर उनकी निगेटिव और / और स्क्रिप्ट्स का उपयोग करके RUN/ या उनके साथ सोर्सिंग करके दोनों परीक्षण कार्यों में किया है NRUN। मेरे लिए, यह ढांचा कम से कम ओवरहेड के लिए सबसे अधिक लाभ प्रदान करता है।


1

मैंने यहाँ प्रस्तुत कई समाधानों की कोशिश की है, लेकिन उनमें से अधिकांश को भारी और उपयोग में कठिन पाया गया है, इसलिए मैंने अपना छोटा परीक्षण ढांचा बनाया: https://github.com/meonlol/t-bash

यह रेपो में केवल एक फाइल है जिसे आप सीधे जोड़ सकते हैं, जो कि JUnit स्टाइल के मूल सेट के साथ है।

मैंने इसे कई आंतरिक परियोजनाओं में पेशेवर रूप से उपयोग किया है और हमारी बैश लिपियों को सुपर स्थिर और प्रतिगमन प्रतिरोधी बनाने में सक्षम था।



0

Outthentic पर एक नज़र डालें , यह सरल है, कई भाषाओं ( एक्सेल , पायथन, रूबी, पसंद पर बैश) और किसी भी कमांड लाइन अनुप्रयोगों का परीक्षण करने के लिए क्रॉस प्लेटफ़ॉर्म (लिनक्स, विंडोज) फ्रेमवर्क द्वारा एक्स्टेंसिबल है।


-2

जब पायथन के इतने बड़े फायदे हुए तो मुझे बड़ी स्क्रिप्ट के लिए बैश का इस्तेमाल करना सही लगा।

  • प्रयास करें / छोड़कर त्रुटि के मामले में परिवर्तनों को पूर्ववत करने की क्षमता के साथ अधिक मजबूत स्क्रिप्ट लिखने की अनुमति देता है।
  • आपको अस्पष्ट सिंटैक्स का उपयोग नहीं करना होगा जैसे कि ' if [ x"$foo" = x"$bar"]; then ...' जिसमें त्रुटियों की संभावना है।
  • getoptमॉड्यूल का उपयोग करके विकल्पों और तर्कों का आसान पार्सिंग (और पार्सिंग तर्कों के लिए एक और भी आसान मॉड्यूल है, लेकिन नाम बच जाता है)।
  • पायथन आपको मूल स्ट्रिंग्स और सरणियों के बजाय सूचियों / डिट्स और ऑब्जेक्ट्स के साथ काम करने की अनुमति देता है।
  • रीजेक्स, डेटाबेस जैसे उचित भाषा टूल तक पहुंच (सुनिश्चित करें कि आप mysqlकमांड में सब कुछ को पॉश में पाइप कर सकते हैं , लेकिन यह कोड लिखने का सबसे अच्छा तरीका नहीं है)।
  • के सही रूप का उपयोग कर के बारे में चिंता करने की कोई आवश्यकता $*या "$*"या "$@"या $1या "$1", फ़ाइल नाम में स्पेस से कोई फ़र्क, आदि, आदि, आदि नहीं है

अब मैं केवल सबसे आसान स्क्रिप्ट के लिए बैश का उपयोग करता हूं।


3
इस तथ्य से इनकार नहीं करते कि पायथन के फायदे हैं लेकिन आपका दूसरा बिंदु बहुत अच्छी तरह से नहीं है। उसी तरह की तुलना की जा सकती है if [[ $foo = $bar ]]; then ...। यह अभी भी बेहतर नहीं है कि अजगर को क्या पेश करना है, लेकिन यह आपके द्वारा प्रस्तुत किए गए से बेहतर है।
श्रीकांत शरत

8
कुछ सिस्टम (उदाहरण के लिए एम्बेडेड) में अजगर उपलब्ध नहीं है और आप अतिरिक्त सामान स्थापित नहीं कर सकते / नहीं कर सकते।
रुई मार्केज

2
मैं व्यक्तिगत रूप से बैश से प्यार करता हूं, लेकिन सहमत हूं कि यह थोड़ा सा टेस्टी हो सकता है। आमतौर पर आपको बहुत अधिक सक्रिय होना पड़ता है जबकि पायथन में आप त्रुटियों के बाद वे आ सकते हैं। हालाँकि, बैश में trap(त्रुटि के मामले में / पूर्ववत करने के लिए) और साथ ही regex (यानी [[ $1 =~ ^[1-3]{3}$ ]]) है। मुझे पूरा यकीन है कि आपके द्वारा उपयोग की जाने वाली अस्पष्ट वाक्य रचना के पुराने कार्यान्वयन के संदर्भ में है test, न कि बैश। बैश मौजूदा कमांड-लाइन टूल्स के साथ इंटरफेस करने के लिए बहुत अच्छा है ... अक्सर पायथन विकल्प की तुलना में एक एकल पाइप awkया grepबहुत आसान है।
छह

1
BTW, जिस पार्सर मॉड्यूल का आप जिक्र कर रहे थे, वह संभवतया optparseइसका उत्तराधिकारी है argparse। मैंने कभी किसी को getoptमॉड्यूल का उपयोग करते नहीं देखा , न ही मैंने इसे व्यक्तिगत रूप से उपयोग किया है। हालांकि getoptउपयोगिता बहुत अच्छी है। एक बार एक अच्छा पैटर्न नीचे लाने के बाद, शेल से आर्ग्युमेंट पार्सिंग एक समस्या नहीं है। जब तक आप गिट-स्टाइल सब-कमांड या कुछ और को लागू करने की कोशिश नहीं कर रहे हैं, यह बहुत परेशानी नहीं है।
छह

पायथन हर जगह नहीं चलेगा जहाँ मार मार सकते हैं। मैं कहता हूं कि क्योंकि हमने बैश बनाम अजगर, समान कोड लॉजिक का परीक्षण किया और दोनों से कुछ करने का अनुरोध किया। बैश ने हर उस निर्देशिका में प्रवेश किया, जिसकी पहुंच थी। दूसरी ओर, अजगर कुछ निर्देशिका अनुमतियों और फ़ाइलों को संभाल नहीं सकता था और वे निर्देशिकाएँ जो बहुत तेजी से बढ़ रही थीं और घट रही थीं।
vianna77
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.