Тестирование устройств bash скриптов

У нас есть система с несколькими скриптами bash, работающими помимо Java-кода. Поскольку мы пытаемся протестировать все, что может быть возможно сломано, и те сценарии bash могут сломаться, мы хотим их протестировать.

Проблема в том, что тестовые скрипты bash трудно проверить.

Есть ли способ или наилучшая практика тестирования скриптов bash? Или мы должны отказаться от использования сценариев bash и искать альтернативные решения, которые можно тестировать?

Ответ 1

Я получил следующий ответ от дискуссионной группы:

можно импортировать (включать, независимо) процедура (функция, независимо от того, что он назвал) от внешнего файл. Это ключ к написанию тестирование script: вы разбиваете свои script в независимые процедуры которые затем могут быть импортированы в оба ваш запуск script и ваше тестирование script, а затем у вас есть бег script быть как можно более простым.

Этот метод похож на инъекцию зависимостей для скриптов и звучит разумно. Предпочтительнее избегать сценариев bash и использовать более проверяемый и менее неясный язык.

Ответ 2

На самом деле существует shunit2, основанная на xUnit инфраструктура модульного тестирования для сценариев оболочки на основе Bourne. Я сам этим не пользовался, но, возможно, стоит проверить.

Подобные вопросы были заданы ранее:

Ответ 3

TAP -compliant Bash testing: Автоматизированная система тестирования Bash

TAP, протокол Test Anything, представляет собой простой текстовый интерфейс между модулями тестирования в тестовом жгуте. TAP начал свою жизнь как часть тестового набора для Perl, но теперь имеет реализации на C, C++, Python, PHP, Perl, Java, JavaScript и других.

Ответ 4

Epoxy - это тестовая среда Bash, разработанная в основном для тестирования другого программного обеспечения, но я использую ее для тестирования модулей Bash а также и Carton.

Основными преимуществами являются относительно низкие накладные расходы на кодирование, неограниченное определение вложенности и гибкий выбор утверждений для проверки.

Я сделал презентацию, сравнивая ее с BeakerLib - рамки, используемые некоторыми в Red Hat.

Ответ 5

Никита Соболев написал отличное сообщение в блоге, в котором сравнил несколько различных сред тестирования bash: Тестирование приложений Bash

Для нетерпеливых: Никита решил использовать Bats, но похоже, что Никита пропустил проект Bats-core, который, как мне кажется, должен был использоваться в качестве исходного проекта Bats. не активно поддерживается с 2013 года.

Ответ 6

Почему вы говорите, что "трудно" протестировать скрипты 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
 }

Ответ 7

Мне очень нравится shell2junit, утилита для генерации JUnit-подобного вывода из Bash script. Это полезно, потому что созданный отчет затем может быть прочитан системами непрерывной интеграции, такими как плагины JUnit для Jenkins и Bamboo.

В то время как shell2junit не предоставляет всеобъемлющую инфраструктуру сценариев Bash, такую ​​как shunit2, это позволяет вам иметь хорошую отчетность о тестировании результаты.

Ответ 8

Попробуйте 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

Вы можете найти несколько примеров здесь и здесь

Ответ 9

Возможно, это можно использовать или внести вклад в

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

Предназначен для записи результатов в TAP-протоколе, который, как мне кажется, хорош для CI, и хорош для тех, кто хочет оболочки оболочки. Я предполагаю, что некоторые вещи выполняются в средах оболочек, поэтому некоторые могут утверждать, что они должны быть протестированы в оболочке.

Ответ 10

Попробуйте assert.sh

source "./assert.sh"

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

Надеюсь, что это поможет!

Ответ 11

Я не могу поверить, что никто не говорил о 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) (часть 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

Установите OSHT_JUNIT или передайте -j чтобы получить вывод JUnit. JUnit также можно комбинировать с prove(1).

Я использовал эту библиотеку как для тестирования функций, получая их файлы, а затем запуская утверждения с IS/OK и их негативами, а также сценарии с помощью RUN/NRUN. Для меня эта структура обеспечивает наибольшую выгоду для наименьших накладных расходов.

Ответ 12

Я создал shellspec, потому что хотел простой и полезный инструмент.

Это написано чистым сценарием оболочки POSIX. Он протестировал со многими снарядами больше, чем shunit2. Он имеет более мощные функции, чем bats/bats-core.

Например, поддержка вложенного блока, простой макет/заглушка, простой пропуск/ожидание, параметризованные тесты, номер строки подтверждения, выполнение по номеру строки, параллельное выполнение, случайное выполнение, средство форматирования TAP/JUnit, интеграция покрытия и CI, профилировщик и т.д..

Смотрите демо на странице проекта.

Ответ 13

Я перепробовал множество решений, представленных здесь, но нашел большинство из них громоздкими и сложными в использовании, поэтому я создал свою собственную небольшую среду тестирования: https://github.com/meonlol/t-bash

Это всего лишь один файл в репо, который вы можете просто запустить напрямую, с базовым набором утверждений стиля JUnit.

Я профессионально использовал его в нескольких внутренних проектах и смог сделать наши bash-скрипты супер стабильными и устойчивыми к регрессии.

Ответ 15

Взгляните на Outthentic, он прост, расширяем многими языками (Perl, Python, Ruby, Bash на выбор) и кроссплатформенными (Linux, Windows) средами для тестирования любых приложений командной строки.

Ответ 16

Мне было трудно обосновать использование bash для больших скриптов, когда Python имеет такие огромные преимущества:

  • Try/Except позволяет писать более надежные скрипты с возможностью отмены изменений в случае ошибки.
  • Вам не нужно использовать скрытый синтаксис, такой как "if [ x"$foo" = x"$bar"]; then ...", который подвержен ошибкам.
  • Простое разбор параметров и аргументов с помощью модуля getopt (и там есть еще более простой модуль для анализа аргументов, но имя ускользает от меня).
  • Python позволяет работать со списками /dicts и объектами вместо основных строк и массивов.
  • Доступ к соответствующим языковым инструментам, таким как регулярное выражение, базы данных (обязательно вы можете передать все в команду mysql в bash, но это не самый приятный способ записи кода).
  • Не нужно беспокоиться об использовании правильной формы $* или "$*" или "[email protected]" или $1 или "$1", пробелы в именах файлов не являются проблемой и т.д. и т.д. и т.д.

Теперь я использую только bash для простейшего сценария.