code

단위 테스트 bash 스크립트

codestyles 2020. 8. 22. 08:55
반응형

단위 테스트 bash 스크립트


Java 코드 외에 실행되는 일부 bash 스크립트가있는 시스템이 있습니다. 우리는 깨질 수있는 모든 것을 테스트하려고하고 있고 그 bash 스크립트가 깨질 수 있기 때문에 우리는 그것들을 테스트하고 싶습니다.

문제는 bash 스크립트를 테스트하기가 어렵다는 것입니다.

bash 스크립트를 테스트하는 방법이나 모범 사례가 있습니까? 아니면 bash 스크립트 사용을 중단하고 테스트 가능한 대체 솔루션을 찾아야합니까?


실제로 Bourne 기반 셸 스크립트를위한 xUnit 기반 단위 테스트 프레임 워크 인 shunit2 가 있습니다 . 나는 그것을 직접 사용하지 않았지만 확인해 볼 가치가있을 것입니다.

유사한 질문이 이전에 제기되었습니다.


토론 그룹에서 다음 답변을 받았습니다.

외부 파일에서 프로 시저 (함수, 이름이 무엇이든)를 가져 오는 것이 가능합니다. 이것이 테스트 스크립트 작성의 핵심입니다. 스크립트를 독립적 인 프로 시저로 분할 한 다음 실행중인 스크립트와 테스트 스크립트로 가져올 수 있으며 실행중인 스크립트를 가능한 한 간단하게 만듭니다.

이 방법은 스크립트에 대한 종속성 주입과 같으며 합리적으로 들립니다. bash 스크립트를 피하고 더 테스트 가능하고 덜 모호한 언어를 사용하는 것이 좋습니다.


TAP 호환 Bash 테스트 : Bash 자동 테스트 시스템

Test Anything Protocol 인 TAP는 테스트 장치의 테스트 모듈 간의 간단한 텍스트 기반 인터페이스입니다. TAP는 Perl 용 테스트 도구의 일부로 시작되었지만 이제는 C, C ++, Python, PHP, Perl, Java, JavaScript 등으로 구현되었습니다.


Epoxy 는 주로 다른 소프트웨어를 테스트하기 위해 디자인 한 Bash 테스트 프레임 워크이지만, 자체Carton을 포함하여 bash 모듈도 테스트하는 데 사용합니다 .

주요 이점은 상대적으로 낮은 코딩 오버 헤드, 무제한 주장 중첩 및 검증 할 주장의 유연한 선택입니다.

Red Hat의 일부에서 사용하는 프레임 워크 인 BeakerLib 과 비교 하여 프레젠테이션을 만들었습니다 .


Nikita Sobolev는 몇 가지 다른 bash 테스트 프레임 워크를 비교하는 훌륭한 블로그 게시물을 작성했습니다. Bash 애플리케이션 테스트

참을성이없는 분들께 : Nikita의 결론은 Bats 를 사용하는 것이었지만 Nikita는 2013 년부터 원래 Bats 프로젝트가 적극적으로 유지되지 않았기 때문에 앞으로 나에게 사용할 것으로 보이는 Bats-core 프로젝트를 놓친 것으로 보입니다.


bash 스크립트를 테스트하는 것이 "어려웠다"는 이유는 무엇입니까?

다음과 같은 테스트 래퍼의 문제점 :

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

나는 Bash 스크립트 테스트에서 JUnit과 같은 출력을 생성하는 유틸리티 인 shell2junit을 아주 좋아 합니다. 생성 된 보고서는 Jenkins 및 Bamboo 용 JUnit 플러그인과 같은 연속 통합 시스템에서 읽을 수 있기 때문에 유용합니다.

shell2junit 같은 포괄적 인 배쉬 스크립트 프레임 워크를 제공하지 않지만 shunit2을 , 당신이 테스트 결과의 좋은보고를 할 수 없습니다.


bashtest 시도 하십시오 . 스크립트를 테스트하는 간단한 방법입니다. 예를 들어, do-some-work.sh일부 구성 파일을 변경했습니다. 예를 들어, PASSWORD = 'XXXXX'구성 파일에 새 행 추가 하십시오 /etc/my.cfg.

bash 명령을 한 줄씩 작성한 다음 출력을 확인합니다.

설치:

pip3 install bashtest

테스트 만들기는 bash 명령을 작성하는 것입니다.

파일 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

여기여기에서 몇 가지 예 를 찾을 수 있습니다.


아마도 이것은 사용되거나 기여할 수 있습니다.

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

Intended to write results in TAP protocol which I imagine is good for CI, and good for those that want shell environments. I imagine some things run in shell environments so, some might argue should be tested in their shell environment.


Give a try to assert.sh

source "./assert.sh"

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

Hope it helps!


I can't believe no one talked about OSHT! It's compatible with both TAP and JUnit, it's pure shell (that is, no other languages involved), it works standalone too, and it's simple and direct.

Testing looks like this (snippets taken from the project page):

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

A simple run:

$ 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

The last test shows as "not ok", but the exit code is 0 because it's a TODO. One can set verbose as well:

$ 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

Rename it to use a .t extension and put it in a t subdirectory, and you can use prove(1) (part of Perl) to run it:

$ 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 or pass -j to produce JUnit output. JUnit can also be combined with prove(1).

I have used this library both testing functions by sourcing their files and then running assertions with IS/OK and their negatives, and scripts by using RUN/NRUN. For me, this framework provides the most gain for the least overhead.


I created shellspec because I wanted a easy-to-use and useful tool.

It written by pure POSIX shell script. It has tested with many shells more than shunit2. It has powerful features than bats/bats-core.

For example, support nested block, easy to mock/stub, easy to skip/pending, parameterized tests, assertion line number, execute by line number, parallel execution, random execution, TAP/JUnit formatter, coverage and CI integration, profiler and etc.

See the demo on the project page.


I’ve tried a lot of the solutions presented here, but found most of them to bulky and hard to use, so I built my own little testing framework: https://github.com/meonlol/t-bash

It’s just one file in the repo that you can simply run directly, with a basic set of JUnit style asserts.

I’ve used it professionally in several internal projects and were able to make our bash scripts super stable and regression resistant.


You might want to take a look at bash_unit:

https://github.com/pgrange/bash_unit


Take a look at Outthentic, it is simple, extensible by many languages ( Perl, Python, Ruby, Bash on choice ) and cross platform ( Linux, Windows ) framework to test any command line applications.


I have found it hard to justify using bash for larger scripts when Python has such huge advantages:

  • Try/Except allows writing more robust scripts with the ability to undo changes in case of an error.
  • You don't have to use obscure syntax such as 'if [ x"$foo" = x"$bar"]; then ...' which is prone to errors.
  • Easy parsing of options and arguments using the getopt module (and there's an even easier module for parsing arguments, but the name escapes me).
  • Python allows you to work with lists/dicts and objects instead of basic strings and arrays.
  • 정규식, 데이터베이스와 같은 적절한 언어 도구에 액세스합니다 (모든 것을 mysqlbash 에서 명령 으로 파이프 할 수 있지만 코드를 작성하는 가장 좋은 방법은 아닙니다).
  • $*또는 "$*"또는 "$@"또는 $1또는 의 올바른 형식을 사용하는 것에 대해 걱정할 필요가 없습니다 "$1". 파일 이름의 공백은 문제 등이 아닙니다.

이제는 가장 간단한 스크립트에만 bash를 사용합니다.

참고 URL : https://stackoverflow.com/questions/1339416/unit-testing-bash-scripts

반응형