- PVSM.RU - https://www.pvsm.ru -
Недавно передо мной встала задача протестировать приложение, написанное на Bash. Изначально я решил использовать unit-тесты на Python, однако, мне не захотелось добавлять лишние технологии в проект. И пришлось выбирать тестовый фреймворк, родным языком которого является многострадальный Bash.
Когда я обратился к Google с запросом: что уже есть на выбор, ответом мне было не так много вариантов. Здесь я рассмотрю некоторые из них.
На какие критерии я буду обращать внимание?
git clone
, wget
.setup()
и teardown()
функций.
Один из первых вариантов, на который я обратил внимание, был небольшой фреймворк assert.sh
. Достаточно хорошее решение: простое в установке, простое в использовании. Для того, чтобы написать первые тесты нужно создать файл tests.sh
и в него написать всего-то (пример из документации):
. assert.sh
# `echo test` is expected to write "test" on stdout
assert "echo test" "test"
# `seq 3` is expected to print "1", "2" and "3" on different lines
assert "seq 3" "1n2n3"
# exit code of `true` is expected to be 0
assert_raises "true"
# exit code of `false` is expected to be 1
assert_raises "false" 1
# end of test suite
assert_end examples
Затем тесты можно запустить и посмотреть результаты:
$ ./tests.sh
all 4 examples tests passed in 0.014s.
Из плюсов можно дополнительно выделить:
-v
), изначально он не говорит, какие тесты падают.Есть несколько серьезных минусов:
setup()
и teardown()
, чтобы можно было подготовить необходимые данные для каждого теста и удалить их по его завершению.Вывод: хороший инструмент, который я бы рекомендовал использовать, если нужно написать пару несложных тестов для скрипта. Для более серьезных задач — не подходит.
Дела с установкой shunit2
обстоят несколько хуже. Я не смог найти адекватного репозитория: есть некий проект на Google.Code, есть несколько проектов на github различной запущенности (3 года и 5 лет), есть даже несколько svn репозиториев. Соответственно, понять, какой релиз последний и откуда его качать — нереально. Но то мелочи. А как выглядят сами тесты? Вот несколько упрощенный пример из документации [5]:
testAdding()
{
result=`expr 1 + 2`
assertEquals
"the result of '${result}' was wrong"
3 "${result}"
}
Выполнение:
$ /bin/bash math_test.sh
testAdding
Ran 1 test.
OK
Данный фреймворк имеет ряд уникальных возможностей в своем классе:
zsh_
, debian_
и т.д.setUp
и tearDown
, которые выполняются для каждого теста, а еще oneTimeSetUp
и oneTimeTearDown
, которые выполняются в начале и в конце тестирования.assert
, есть возможность выводить номера строк, где падает тест, используя конструкцию ${_ASSERT_EQUALS_}
, но только в оболочках, где поддерживается нумерация строк. Из документации: bash
(>=3.0), ksh
, pdksh
, и zsh
.Но есть и ряд существенных минусов, которые меня в итоге и оттолкнули:
assertEquals
и assertSame
. Мелочь, а удивляет.
Вывод: серьезный инструмент, который можно гибко настроить и превратить в незаменимую часть проекта, но пугает отсутствие внятной системы ведения проекта самого shunit2
. Я решил искать дальше.
Меня первоначально заинтересовал данный фреймворк, потому что он написан автором Sinatra
для Ruby
. А еще понравился синтаксис тестов, который напоминает привычный и знакомый Mocha
[7]. По-умолчанию запускаются все функции, которые начинаются с it_
внутри файла. Что интересно, все тесты запускаются внутри собственного sandbox, что позволяет не допускать лишних ошибок. А вот как выглядят сами тесты, пример из документации:
describe "roundup(5)"
before() {
foo="bar"
}
after() {
rm -f foo.txt
}
it_runs_before() {
test "$foo" "=" "bar"
}
Примеров вывода нет, чтобы посмотреть — нужно поставить и проверить, плохо. Вот какие есть достоинства:
git clone
и ./configure && make
, можно установить в локальную директорию с добавлением в $PATH
.И минусов набралось достаточно:
source
каких-то общих функций для всех тестов, но справедливости ради стоит сказать, что при помощи хака — можно.TODO
, а работы не ведутся уже пару лет.
Вывод: абсолютно средняя такая штука, нельзя сказать, что плохая. Но и хорошей ее не назовешь. По функционалу схожа с assert.sh
, только чуть больше. Где использовать? Если хватает функционала assert.sh
, но нужна функция before()
или after()
.
Скажу сразу, остановил свой выбор на данном фреймворке. Понравилось многое. Прежде всего — отличная документация: примеры использования, семантическая версификация, отдельно порадовал список проектов, которые используют bats
.
bats
использует следующий подход: тест считается пройденным, если все команды внутри него возвращают код 0
(как set -e
). То есть каждая строка — проверка истинности. Вот как выглядят тесты, написанные на bats
:
#!/usr/bin/env bats
@test "addition using bc" {
result="$(echo 2+2 | bc)"
[ "$result" -eq 4 ]
}
@test "addition using dc" {
result="$(echo 2 2+p | dc)"
[ "$result" -eq 4 ]
}
И вывод:
$ bats addition.bats
✓ addition using bc
✓ addition using dc
2 tests, 0 failures
Вывод информации о тестах при помощи флага (--tap
) можно представить в виде текста совместимого с Test Anything Protocol
[9], для которого есть плагины для большего количества программ: Jenkins, Redmine и прочие.
В bats
, помимо особенного синтаксиса для написания теста, есть много интересного:
run
позволяет запустить команду, а затем протестировать ее выходной код и текстовый вывод: для чего есть специальные переменные: $status
и $output
load
позволяет загрузить для использования общую кодовую базу.skip
позволяет пропустить тест при необходимости.setup()
и teardown()
позволяют настроить окружение и прибрать за собой.
Плюсов у bats
объективно много, и я уже их перечислил, а вот минус я смог заметить только один:
bats
отходит от валидного bash
. Тесты необходимо писать в файлах с разрешением .bats
, использовать другой shebang.Вывод: качественный инструмент, практически без слабых мест. Советую к использованию.
Если интересно посмотреть, что же получилось в итоге, то вот ссылка на тесты [11] к моему free-time проекту git-secret
[12].
Автор: sobolevn
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/bash/114546
Ссылки в тексте:
[1] Travis: https://travis-ci.com/
[2] assert.sh: https://github.com/lehmannro/assert.sh
[3] момент написания статьи: https://travis-ci.org/lehmannro/assert.sh/builds/74633036
[4] shunit2: https://github.com/kward/shunit2
[5] документации: https://shunit2.googlecode.com/svn/trunk/source/2.1/doc/shunit2.html#asserts
[6] roundup: https://github.com/bmizerany/roundup
[7] Mocha
: https://mochajs.org/
[8] bats: https://github.com/sstephenson/bats
[9] Test Anything Protocol
: http://testanything.org/
[10] целый набор специальных переменных среды: https://github.com/sstephenson/bats#special-variables
[11] ссылка на тесты: https://github.com/sobolevn/git-secret/tree/master/tests
[12] git-secret
: https://sobolevn.github.io/git-secret/
[13] Источник: https://habrahabr.ru/post/278937/
Нажмите здесь для печати.