26.06.2012 20:14, "Артём Н." пишет:
26.06.2012 12:54, Igor Chumak пишет:
25.06.2012 18:03, "Артём Н." пишет:
Я "наворачиваю" не для того, чтобы "круто на баш написать" и не из-за проблем с
головой, а для того, чтобы попробовать TDD (или хотя бы просто unit тесты) там,
где его обычно не используют... На перспективу. Пока что, не особенно хорошо
получается. :-)
Было бы интересно посмотреть.
Да что там интересного? Я только пытаюсь, пока-что. Взял небольшую задачу,
которую требуется выполнить. Конкретно: требуется бэкап-скрипт. Но нужно
сохранять не только иерархию каталогов, но и некоторые служебные данные: LVM,
LUKS заголовки, дамп БД и т.п.. Причём, используя для бэкапа тот же самый
rdiff-backup, который используется для сохранения каталогов.
Каталоги для сохранения - в отдельном списке.
Развернуть bacula будет быстрее ;)
На очереди задачка побольше, поэтому думаю, стоит попробовать на совсем
небольшом.
Для этого я сделал:
1. Функцию assert:
###TESTING
assert()
# $1 - message;
# $2 - comannd.
{
echo "Command: $2"
eval $2 || { echo "$1"&& exit 1; }
return 0;
}
###/TESTING
2. Теги ###TESTING ###/TESTING.
Не мудрствуя лукаво, реализовав обработку на awk:
#!/bin/sh
fl="$1"
fl=${-:-$fl}
awk '
BEGIN {
prf = 0;
}
/^#!\/bin\/bash/ {
print "#!/bin/sh";
next;
}
/###TESTING/ {
prf = pfm + 1;
next;
}
/###\/TESTING/ {
if (prf == 0)
{
print "Error: unexpected ###\/TESTING"> "/dev/stderr";
exit 1;
}
prf = prf - 1;
next;
}
{
if (prf == 0) print;
}
END {
if (prf> 0)
{
print "Error: unclosed ###TESTING";
exit 1;
}
}
' "$fl"
Это мы проверяем скрипт на связность тегов ###TESTING и ###/TESTING?
А смысл?
grep "###/*TESTING" script.sh выведет теги на экран, глаз несвязность и
так заметит. Единоразово прокатит, а автоматически проверять - не вижу
смысла.
3. Функцию dbg со товарищи, для вывода сообщений, соответствующих уровню
"разговорчивости":
dbg()
# $1 - verbosity level;
# $2 - message.
{
[ "$V_LEVEL" -ge "$1" ]&& echo "$2"> /dev/stderr
}
err()
# $1 - message.
{
dbg 1 "$1"
dbg 0 "Backup failed..." # failed...&& exit 1
return 1
}
Вложенные функции (в функции сохранения служебной информации каждое действие
оформлено маленькой функцией, вложенной в основную) проверяются модульными
тестами внутри "функции-родителя" (в тегах ###TESTING).
Каждая внешняя функция проверяется в главной функции, заменяющей реальную
главную.
(Например, вызывается main, которая переопределяется в тегах ###TESTING, на
вызов тестирующей функции).
В итоге получается какой-то намёк на модульные тесты, плюс на что-то
"интегративное".
Внутри каждой тестирующей функции проверяется правильное поведение и реакция на
ошибку (в случае ошибки, функция должна возвращать свой код отличный от нуля или
$?, если была выполнена команда перед завершением). Ну и "граничные условия",
если имеются.
К примеру:
assert "backup_kernel_conf error 0" "backup_kernel_conf bla-bla-bla...
\"$PWD/_config\"||true"
assert "backup_kernel_conf error 1" "backup_kernel_conf \"$LINUX_CONFIG\"
\"$PWD/_config\""
Сделано грязновато, но хоть что-то... К TDD это относится мало. Разве что, я
пытаюсь вначале писать тесты.
Собственно, на этом всё.
Как-то все сложно.. Зачем TDD в обертке вокруг rdiff-backup? Я вижу
процесс архивирования так:
прочитали конфиг || свалились по ошибке
запустили pre-backup скрипт || свалились по ошибке
запустили backup || свалились по ошибке
запустили post-backup скрипт || свалились по ошибке
обновили каталог || свалились по ошибке
отправили уведомления
не вижу я здесь места для 100500 вложенных функций с кучей параметров ;)
--
To UNSUBSCRIBE, email to debian-russian-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: http://lists.debian.org/4feac2bb.2040...@gmail.com