Java 코드 외에 실행되는 일부 bash 스크립트가있는 시스템이 있습니다. 우리는 깨질 수있는 모든 것을 테스트하려고하고 있고 그 bash 스크립트가 깨질 수 있기 때문에 우리는 그것들을 테스트하고 싶습니다.
문제는 bash 스크립트를 테스트하기가 어렵다는 것입니다.
bash 스크립트를 테스트하는 방법이나 모범 사례가 있습니까? 아니면 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 등으로 구현되었습니다.
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
}
사용하기 쉽고 유용한 도구를 원했기 때문에 shellspec을 만들었습니다 .
순수한 POSIX 쉘 스크립트로 작성되었습니다. shunit2보다 많은 쉘로 테스트했습니다. 그것은 박쥐 / 박쥐 코어보다 강력한 기능을 가지고 있습니다.
예를 들어, 중첩 된 블록 지원, 모의 / 스텁 용이, 건너 뛰기 / 보류 용이, 매개 변수화 된 테스트, 어설 션 라인 번호, 라인 번호 별 실행, 병렬 실행, 임의 실행, TAP / JUnit 포맷터, 커버리지 및 CI 통합, 프로파일 러 등 .
프로젝트 페이지에서 데모를 참조하십시오.
나는 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/
내가 생각하기에 CI에 좋고 쉘 환경을 원하는 사람들에게 좋은 TAP 프로토콜로 결과를 작성하려고했습니다. 나는 어떤 것들은 쉘 환경에서 실행될 것이라고 생각한다. 그래서 어떤 이들은 쉘 환경에서 테스트되어야한다고 주장 할 것이다.
assert.sh를 시도 하십시오.
source "./assert.sh"
local expected actual
expected="Hello"
actual="World!"
assert_eq "$expected" "$actual" "not equivalent!"
# => x Hello == World :: not equivalent!
도움이 되었기를 바랍니다.
나는 아무도 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
마지막 테스트는 "not ok"로 표시되지만 종료 코드는 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)
(Perl의 일부)를 사용하여 실행할 수 있습니다.
$ 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
. 저에게이 프레임 워크는 최소한의 오버 헤드로 가장 많은 이득을 제공합니다.
여기에 제시된 많은 솔루션을 시도했지만 대부분의 솔루션이 부피가 크고 사용하기 어려웠 기 때문에 자체 테스트 프레임 워크를 구축했습니다 : https://github.com/meonlol/t-bash
JUnit 스타일 어설 션의 기본 세트를 사용하여 간단하게 직접 실행할 수있는 저장소에있는 하나의 파일입니다.
여러 내부 프로젝트에서 전문적으로 사용했으며 bash 스크립트를 매우 안정적이고 회귀에 강하게 만들 수있었습니다.
bash_unit을 살펴볼 수 있습니다.
Outthentic을 살펴보면 간단하고 다양한 언어 (Perl, Python, Ruby, Bash on choice) 및 크로스 플랫폼 (Linux, Windows) 프레임 워크로 확장하여 모든 명령 줄 애플리케이션을 테스트 할 수 있습니다.
파이썬 에 엄청난 이점이 있을 때 더 큰 스크립트에 bash를 사용하는 것을 정당화하기가 어렵다는 것을 알았습니다 .
if [ x"$foo" = x"$bar"]; then ...
오류가 발생하기 쉬운 ' ' 와 같은 모호한 구문을 사용할 필요가 없습니다 .getopt
모듈을 합니다 (그리고 인수를 파싱하기위한 더 쉬운 모듈이 있지만 이름은 나를 탈출합니다).mysql
bash 에서 명령 으로 파이프 할 수 있지만 코드를 작성하는 가장 좋은 방법은 아닙니다).$*
또는 "$*"
또는 "$@"
또는 $1
또는 의 올바른 형식을 사용하는 것에 대해 걱정할 필요가 없습니다 "$1"
. 파일 이름의 공백은 문제 등이 아닙니다.이제는 가장 간단한 스크립트에만 bash를 사용합니다.
if [[ $foo = $bar ]]; then ...
. 이것은 파이썬이 제공하는 것보다 낫지는 않지만 당신이 제시 한 것보다 낫습니다.
trap
정규식 (예 :)뿐만 아니라 (오류 발생시 정리 / 실행 취소 [[ $1 =~ ^[1-3]{3}$ ]]
) 기능이 있습니다. 나는 당신이 사용한 모호한 구문이 test
bash가 아닌의 이전 구현에 대한 참조라고 확신합니다 . 강타는 자주 하나의 파이프로 ... 기존 명령 줄 도구와의 인터페이스를 위해 중대하다 awk
또는 grep
파이썬 대안보다 훨씬 쉽습니다.
optparse
그 후속 모듈 일 것 argparse
입니다. 나는 아무도 getopt
모듈을 사용하는 것을 본 적이 없으며 개인적으로 사용하지 않았습니다. 그러나 getopt
유틸리티는 훌륭합니다. 셸에서 인수 구문 분석을 수행하는 것은 좋은 패턴을 얻은 후에는 전혀 문제가되지 않습니다. git 스타일의 하위 명령 등을 구현하지 않는 한 큰 문제가 아닙니다.