Блок скриптів тестування блоку


112

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

Проблема в тому, що важко перевірити bash-скрипти.

Чи є спосіб чи найкраща практика для тестування сценаріїв bash? Або ми повинні кинути використання bash-скриптів і шукати альтернативні рішення, які можна перевірити?




Огляд існуючих інструментів: medium.com/wemake-services/…
sobolevn

Відповіді:


48

Насправді існує shunit2 , тестова основа на основі xUnit для скриптів оболонки на основі Bourne. Я його ще не використовував, але це, можливо, варто перевірити.

Подібні запитання задавались і раніше:


3
Я можу стверджувати (каламбур), що shunit2 (версія 2.1.6) на сьогоднішній день трохи зламаний. Assemblyrtull і assertNotNull не працюють, навіть якщо ви подаєте їм прямі значення. assertEquals працює чудово, але я думаю, що мені зараз доведеться прокрутити своє.
лабіринт

@labyrinth, ви впевнені, що проблема була не в цьому: github.com/kward/shunit2/isissue/53 "Як правильно використовувати assertNull?"
Віктор Сергієнко

1
@Victor Однозначно можливо, я не був достатньо обережним зі своїми подвійними цитатами. Незабаром я переходжу до ролі, коли shunit2 або якась система баш-тестування буде дуже корисною. Я спробую ще раз.
лабіринт

5
Я користувач і іноді дописуюсь до shunit2, і можу підтвердити, що проект живий і здоровий у 2019 році.
Алекс Харві

31

Я отримав таку відповідь від дискусійної групи:

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

Цей метод схожий на введення залежності для сценаріїв, і звучить розумно. Уникання баш-скриптів та використання більш тестової та менш незрозумілої мови є кращим.


4
Я не впевнений, чи варто проголосувати вгору чи вниз, з одного боку поділ на менші частини - це добре, але з другого боку мені потрібна рамка, а не набір призначених для користувача сценаріїв
mpapis

10
Хоча в bash немає нічого поганого (я написав багато, багато сценаріїв), це важко освоїти. Моє правило - якщо сценарій досить великий, щоб вимагати тестів, ви, ймовірно, повинні перейти до мови сценаріїв, яка легко перевіряється.
Дуг

1
Але іноді потрібно мати щось, що можна знайти в оболонці користувачів. Мені незрозуміло, як би ви це зробили, не вдаючись до сценарію оболонки
Itkovian

@Itkovian - ви можете, наприклад, використовувати npm для експорту виконуваного файлу до контуру, тому джерело пошуку не потрібно (ваш пакет npm повинен бути встановлений у всьому світі)
Еліран Малька,

1
Я збираюся дотримуватися порад щодо використання bash. :)
Maciej Wawrzyńczuk

30

Тест Bash, сумісний з TAP : Автоматизована система тестування Bash

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


14
Варто розкрити, що таке TAP і чому слід піклуватися, інакше це просто безглузда копія-вставка
om-nom-nom

@ om-nom-nom: зараз я пов’язав це із сайтом TAP.
Янус Троельсен

7
Оскільки ніхто інший не казав несказаного: TAP = Test Anything Protocol
JW.

9

Микита Соболєв написав чудову публікацію в блозі, де порівнював декілька різних рамок тестування bash : Тестування програм Bash

Для нетерплячих: висновок Нікіти полягав у використанні Батів, але, схоже, Микита пропустив базовий проект Батса, який, як мені здається, є тим, хто повинен рухатися вперед, оскільки оригінальний проект кажанів не вевся активно з 2013 року.


7

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

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

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


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
 }

4
По-перше, сценарії bash не дуже читабельні. По-друге, очікування складні, як перевірка, чи створюється файл блокування з PID скрипту bash, який його створив.
nimcap

10
Що ще важливіше, важко перевірити сценарії оболонки, оскільки вони, як правило, мають велику кількість побічних ефектів і використовують системні ресурси, такі як файлова система, мережа тощо. В ідеалі одиничні тести не мають побічних ефектів і не залежать від системних ресурсів.
jayhendren

4

Я створив shellspec тому що хотів простий у використанні та корисний інструмент.

Він написаний за допомогою чистого сценарію оболонки POSIX. Він протестував з багатьма снарядами більше, ніж shunit2. Він має потужніші характеристики, ніж кажани / кажани-стрижні.

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

Дивіться демонстрацію на сторінці проекту.


3

Мені дуже подобається shell2junit , утиліта для генерування JUnit-подібного виходу з тестів сценарію Bash. Це корисно, оскільки згенерований звіт потім може бути прочитаний системами безперервної інтеграції, такими як плагіни JUnit для Jenkins та Bamboo.

Хоча shell2junit не забезпечує всеосяжної рамки сценаріїв Bash, як shunit2 , вона дозволяє приємно звітувати про результати тесту.


3

Спробуйте баштест . Це простий спосіб перевірити свої сценарії. Наприклад, у вас є 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

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


3

Можливо, це можна використати чи сприяти

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

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


3

Спробуйте спробувати assert.sh

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, тому що це "a" 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. Для мене ця рамка забезпечує найбільшу вигоду за найменші накладні витрати.


1

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

Це просто один файл у репо, який ви можете просто запустити безпосередньо, з основним набором тверджень у стилі JUnit.

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



0

Погляньте на Outthentic , це просто, розширюється багатьма мовами (Perl, Python, Ruby, Bash на вибір) та кросплатформова (Linux, Windows) рамка для тестування будь-яких програм командного рядка.


-2

Мені важко виправдати використання bash для великих сценаріїв, коли Python має такі величезні переваги:

  • Спроба / Виняток дозволяє писати більш надійні сценарії з можливістю скасування змін у разі помилки.
  • Не потрібно використовувати незрозумілий синтаксис, наприклад " if [ x"$foo" = x"$bar"]; then ...", схильний до помилок.
  • Легкий аналіз параметрів та аргументів за допомогою getoptмодуля (а ще більш простий модуль для аналізу аргументів, але ім'я уникає мене).
  • Python дозволяє працювати зі списками / диктами та об'єктами замість основних рядків та масивів.
  • Доступ до належних мовних інструментів, таких як регулярний вираз, бази даних (впевнений, що ви можете передати все в mysqlкоманду в bash, але це не найкращий спосіб написання коду).
  • Немає необхідності турбуватися про використання правильної форми $*або "$*"або "$@"або $1або "$1", пробілу в іменах файлів не є проблемою, і т.д., і т.д., і т.д.

Тепер я використовую лише bash для найпростіших сценаріїв.


3
Не заперечуючи факту, що Python має переваги, але ваш другий пункт не дуже вдалий. Таке ж порівняння можна було б зробити як if [[ $foo = $bar ]]; then .... Це все ще не краще того, що може запропонувати пітон, але краще, ніж те, що ви представили.
Шрікант Шарат

8
У деяких системах (вбудованих напр.) Немає доступного python, і ви не можете / не бажаєте встановлювати додаткові матеріали.
Rui Marques

2
Я особисто люблю баш, але згоден, що це може бути трохи випробувальним. Зазвичай ви повинні бути набагато активнішими, тоді як в Python ви можете вирішувати помилки після їх появи. Однак у bash є trap(для очищення / скасування в разі помилки), а також регулярний вираз (тобто [[ $1 =~ ^[1-3]{3}$ ]]). Я впевнений, що невідомий синтаксис, який ви використовували, стосується старих реалізацій test, а не bash. Bash чудово підходить для взаємодії з існуючими інструментами командного рядка ... Часто одна труба awkабо grepнабагато простіше, ніж альтернатива Python.
Шість

1
BTW, модуль аналізатора, на який ви посилалися, ймовірно, optparseабо його наступник argparse. Я ніколи не бачив, щоб хтось використовував getoptмодуль, і не використовував його особисто. Однак getoptкорисність велика. Аналіз аргументів з оболонки взагалі не є проблемою, коли у вас є приємний зразок. Якщо ви не намагаєтесь реалізувати підкоманди в стилі git чи щось подібне, це не так вже й багато проблем.
Шість

Python не працюватиме скрізь, де баш може досягти. Я кажу, що тому, що ми протестували bash проти python, таку ж логіку коду, і попросили обох щось зробити. Bash входив у кожен каталог, до якого він мав доступ. З іншого боку, python не міг обробляти деякі дозволи та каталоги, а також каталоги, які дуже швидко зростали та зменшувалися.
vianna77
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.