Тестирование и отладка Shell-скриптов#
Тестирование#
Bats#
Bats — это фреймворк для тестирования Bash-скриптов. Bats предоставляет Bash-совместимый синтаксис для написания тестовых скриптов. Имеет не самую плохую документацию. Я не буду здесь её пересказывать, а просто покажу примеры тестов.
Следует отметить, что для нормального экспириенса потребуется в папку с проектом доставить из Git’а как минимум пару субмодулей (helpers) для Bats. В моём случае:
git submodule add https://github.com/bats-core/bats-assert.git tests/helpers/bats-assert
git submodule add https://github.com/bats-core/bats-support.git tests/helpers/bats-support
git commit -m 'Add bats-assert and bats-support libraries'
Хэлперы подключаются в тестовых скриптах в специальной функции setup()
.
Здесь я тестирую функцию parse_uri()
из файла lib/uri.sh. Функция принимает строку c URI и задаёт набор переменных с соответствующими компонентами URI. В тесте я проверяю, что значения этих переменных соответствуют ожидаемым. Обратите внимание на шебанг, тестовый файл также имеет расширение .bats для наглядности.
На 19-й строке я читаю uri.sh и далее вызываю функцию с аргументом. Сопоставление переменых со значениями проверяется обычным test(1)-ом. Тест будет провален, если тестируемый скрипт выйдет с ненулевым кодом.
1#!/usr/bin/env bats
2
3# parse_uri() from lib/uri.sh tests.
4# See: https://bats-core.readthedocs.io/en/latest/index.html
5
6setup() {
7 # Bats setup
8 load 'helpers/bats-support/load'
9 load 'helpers/bats-assert/load'
10 DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )"
11 PATH="$DIR/../src/lib:$PATH"
12}
13
14# ------------------------------ #
15# Do tests! #
16# ------------------------------ #
17
18@test "http://user:password@host:port/path?q=val" {
19 . uri.sh
20 parse_uri 'http://user:password@host:123/path?q=val'
21 [ "$scheme" == 'http' ]
22 [ "$hostname" == 'host' ]
23 [ "$port" == '123' ]
24 [ "$path" == '/path' ]
25 [ "$username" == 'user' ]
26 [ "$password" == 'password' ]
27 [ "$query" == 'q=val' ]
28 [ "$fragment" == '' ]
29}
Вот так можно проверить STDOUT скрипта (я проверяю здесь функцию, но суть не изменится для файла):
1@test "Bad script syntax" {
2 . source.sh
3 __user_script=script.sh
4 run source_script $DIR/files/bad_syntax.sh
5 assert_output --partial 'Error: script.sh: Please check your syntax'
6}
Тест будет провален, если функция source_script()
не вернёт текст ошибки если скормить ей заведомо некорректные данные.
Тесты запускаются так:
bats --verbose-run --print-output-on-failure parse_uri.bats
Shpec#
Ещё одна тулза для написания тестов. Пока не потыкал, но выглядит потенциально очень интересно. Возможно будет удобней Bats.
Отладка#
Самописные решения#
Bash отладчик с поддержкой произвольных точек останова: https://habr.com/ru/post/674732/
Как отлаживать bash-script-ы по шагам: https://habr.com/ru/post/666982/
BASHDB#
Пока пользоваться не приходилось, но если буду, обязательно здесь опишу.
Линтинг#
Shellckeck#
Shellckeck это крайне полезный инструмент для быстрого улучшения кода. Он покрывает очень много кейсов и помогает закрыть по крайней мере часть потенциальных ошибок в скриптах.
Shellckeck анализирует код на предмет вредных и опасных паттернов и даёт подсказки по стилю кода. На каждое выдаваемое программой замечание есть отдельная статья в Wiki с обоснованием такого решения. Мешающие проверки можно отключить в коде с помощью специально оформленных комментариев.
Утилита есть в репозиториях большинства дистрибутивов. Пользоваться ей очень просто:
shellcheck my_script.sh