Тестирование веб-ориентированных приложений. Часть-1: инсталляционное тестирование.

Инсталляционное тестирование
О тестировании как таковом написано много. О тестировании веб-ориентированных приложений – меньше и, как правило, рассматриваются отдельные технологии и/или программные средства. Об инсталляционном тестировании веб-ориентированных приложений написано ещё меньше.

В этой серии заметок предлагаю рассмотреть вопрос о том, как повысить качество относительно простых (индивидуально-фрилансерских или выполненных силами 3-5-7 человек в небольшой дизайн-студии) веб-ориентированных приложений.

Начну с морализаторства. Не стоит называть данную предметную область "тестированием сайтов". Да, очень часто веб-ориентированное приложение представляет собой движок сайта. Часто, но не всегда. И даже в состав движка может входить несколько вполне самостоятельных приложений.

Вторая вводная: говорить будем о тестировании веб-ориентированных приложений, написанных на PHP. Хоть и затронем JavaScript, CSS, (X)HTML и т.п.

Рассматривать процесс тестирования будем с точек зрения разработчика (что и как сделать), заказчика (что ожидает пользователь) и тестировщика (что и как проверять) проекта, т.к. такой подход делает более очевидными некоторые проблемы.

Инсталляционное тестирование — тестирование, направленное на выявление дефектов программного обеспечения, влияющих на протекание стадии инсталляции (установки) и деинсталляции (удаления) приложения.

Многие (особенно – начинающие) разработчики напрочь забывают о том, что их программное средство будет работать не только на том компьютере, на котором оно разрабатывалось. И начинается: не та версия того или иного ПО, отсутствуют какие-то библиотеки, где-то жёстко прописаны пути и т.п. В случае "штучных" проектов это правится руками. В случае "массовых" проектов… нет, проекты, написанные ТАК, массовыми не становятся.

Итак, поехали.

Пути. Ещё на стадии разработки следует принять в качестве стандарта использование только относительных путей с префиксами, позволяющими прекратить их в абсолютные. Т.е. вместо

$path1="c:/www/images/";
$path2="/images/";
$path3="../images/";
// и т.п.

следует писать

$path=$path_prefix."images/";

где $path_prefix задаётся в процессе инсталляции (можно попробовать определить его автоматически на основе данных из массива $_SERVER).

Второе магическое правило: только нижний регистр, только латиница (буквы, цифры, знак подчёркивания). Без исключений. Это сразу отметает проблему "под виндой всё работает, а под никсами — нет". Знак подчёркивания вместо тире – хороший способ не путать на подсознательном уровне пути и арифметические выражения.

Техники: проверить корректность путей помогает анализ на наличие битых ссылок и общее функциональное тестирование продукта. Если до полноценного функционального тестирования в мелких фирмах руки часто не доходят, то проверить ссылки – это святое. Используем софт: Semonitor, онлайновый валидатор (особенно удобно, когда сайт уже выгружен на хостинг) Link Checker), Xenu’s Link Sleuth (хорошее описание смотрите здесь) и т.д. Подобных утилит и сервисов много.

Допустим, с путями мы разобрались.

Инсталлятор. Второе, о чём следует сказать, — необходимость наличия хоть какого-нибудь инсталлятора. Даже если ваше приложение простое, как кирпич, можно написать скрипт, который проверит, всё ли хорошо.

Что проверяем:

1. Наличие и размер (можно и md5-хэш) всех входящих в инсталляционный комплект файлов. Часто можно встретить ситуацию, когда что-то не докачалось, повредилось и т.п. Эту информацию можно хранить в явном виде в массиве.

2. Наличие свободного места на диске. Используем функцию disk_free_space(). Оценку проводим по двум параметрам:

а) Хватит ли места на завершение инсталляции (это – обязательно, если в процессе инсталляции мы создаём новые файлы).

б) Достаточно ли свободного места для устойчивой работы программного средства хотя бы в ближайшее время. Так, например, глупо ждать светлого будущего от фото-галереи, которой осталось доступно 10 Мб дискового пространства.

Кстати: хороший инсталлятор проверяет наличие свободного месса на диске перед каждой дисковой операцией, которой это место может понадобится. Это позволяет исключить ситуацию "проверили, начали инсталляцию, какой-то другой софт занял свободное место, инсталляция завершалась крахом".

3. Ограничения доступного скрипту объёма оперативной памяти, времени выполнения и т.п.

ini_get(‘max_execution_time’);
ini_get(‘max_input_time’);
ini_get(‘max_input_nesting_level’);
ini_get(‘memory_limit’);

Если чего-то нам не хватает – сообщаем об этом.

4. Версию PHP (функцией phpversion(); ), загруженные расширения (функцией get_loaded_extensions(); ) и версии конкретных расширений (как вариант, иногда можно проверять доступность нужных мам функций с помощью function_exists(); ).

5. Версию СУБД, возможность подключения (корректность логина, пароля, наличие используемой БД). Так, например, для MySQL это легко сделать с помощью mysql_connect(), mysql_select_db(),mysql_get_server_info().

6. Версию веб-сервера ($_SERVER[‘SERVER_SOFTWARE’]) и (если это важно) значения тех или иных его параметров (многое можно узнать из всё того же массива $_SERVER).

7. Операционную систему. Вообще, хороший код на PHP получается почти платформенно-независимым. Почти. Иногда от использования системно-специфических функций отказаться не удаётся. Тогда удостоверяемся, что скрипт запущен под поддерживаемой ОС (включая версию).

8. Возможность установки исходящих соединений (если они необходимы приложению). Достаточно просто открыть сокет функцией fsockpoen().

9. Значение критических для безопасности, производительности и даже общей работоспособности приложения параметров PHP, таких как register_globals, allow_url_fopen, post_max_size и т.п. Всё это можно сделать функцией ini_get().

10. Всё или почти всё вышеперечисленное можно адаптировать для самодиагностики приложения на случай "всё работало и вдруг перестало". Можно повторить проверку параметров среды исполнения и, если обнаружатся недопустимые отклонения, выслать уведомление администратору приложения. Откуда возьмутся отклонения? Например, хостер обновил или перенастроил ПО на сервере.

11. Если проект предполагает установку и настройку разработчиком, здорово облегчить себе жизнь можно с применением модульного тестирования (смотрите эту и эту заметки). Наличие модульных тестов позволяет чудесно протестировать приложение в новой среде выполнения.

Выполнение вышеперечисленных пунктов, фактически, позволяет автоматизировать процесс инсталляционного тестирования средствами самого PHP и сделать этот процесс универсальным (не зависящим от какого бы то ни было инструментального средства). Такой подход также позволяет приложению адаптироваться под среду выполнения (использовать соответствующие наборы функций).

Также следует помнить о том, что инсталляционное тестирование призвано проверить такие случаи:

а) новая среда исполнения, в которой приложение ранее не было инсталлировано (это мы только что рассмотрели);
б) обновление существующей версии ("апгрейд");
в) изменение текущей версии на более старую ("даунгрейд");
г) повторная установка приложения с целью устранения возникших проблем ("переинсталляция");
д) повторный запуск инсталляции после фатальной ошибки, приведшей к невозможности продолжения инсталляции;
е) удаление приложения;
ж) установка нового приложения из семейства приложений (например, мы выпускам форум и блог);

В пунктах "б" и "в" особое внимание следует уделить вопросу сохранности данных. Следует также настойчиво предложить пользователю сделать резервную копию базы данных, файлов данных и файлов приложения (можно даже автоматизировать этот процесс).

Пункт "г" в веб-ориентированных приложениях на PHP встречается крайне редко. Намного проще восстановить приложение из резервной копии или выполнить (при его наличии) специальный скрипт самодиагностики и самовосстановления. Однако, многие пользователи привыкли к тому, что "раз не работает – надо переставить". Приложение должно в такой ситуации информировать пользователя об альтернативных вариантах решения проблем, предлагать сделать резервную копию и НЕ удалять данные пользователя ни из базы данных, ни с диска.

Возникновение пункта "д" – плохой симптом. Но, допустим, это случилось по объективным причинам (например, в результате сбоя аппаратного обеспечения). Тогда приложение должно быть в состоянии или продолжить инсталляцию с того места, где она была прервана, или начать её заново, "аннулировав" все предыдущие действия (удалив из базы данных и с диска свои "старые" файлы и данные.

Пункт "е" печален для разработчика приложения, но тоже встречается. Приложение должно ПОЛНОСТЬЮ удалить себя из системы. Существует золотое правило: "система до установки приложения и после его удаления должна выглядеть совершенно одинаково". Это значит, что нельзя допустить "забывания" приложением каких-то своих файлов или данных в БД. Здесь снова встаёт вопрос создания резервной копии (на случай, если что-то пойдёт не так или пользователь передумает). Отдельным пунктом стоит вопрос об удалении из базы данных и с диска "пользовательской информации" (например – сообщений форума и аватарок его пользователей). Следует предоставить пользователю возможность решить, что делать с этими данными (оставить, удалить, сделать их резервную копию и т.п.)

Пункт "ж" особенно опасен тем, что одно приложение может повредить данные другого (перезаписать своими в процессе инсталляции или, посчитав своими, удалить в процессе деинсталляции).

Все пункты с "а" по "ж" включительно также следует рассмотреть с точки зрения установки модулей приложения, если такая функция поддерживается.

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

Теперь переходим к точке зрения тестировщика. Рассмотрим чек-лист инсталляционного тестирования веб-ориентированного приложения на PHP. Заранее уточню: для какого-то специфического приложения чек-лист может сильно отличаться от предложенного ниже.

Чек-лист:

  1. Позволяет ли инсталлятор указывать пути размещения скриптов и файлов данных, данные для сединения с СУБД, имя БД и тому подобную информацию?
  2. Проверяет ли инсталлятор наличие всех необходимых файлов перед началом инсталляции?
  3. Проверяет ли инсталлятор целостность всех необходимых файлов перед началом инсталляции?
  4. Проверяет ли инсталлятор, хватит ли места на диске для установки ПС?
  5. Проверяет ли инсталлятор, достаточно ли на диске места для устойчивой работы ПС?
  6. Проверяет ли инсталлятор настройки PHP, критичные для работы ПС (объём памяти, выделяемой скрипту, максимальное время выполнения скрипта и т.п.)?
  7. Проверяет ли инсталллятор версию PHP/Apache/MySQL/ОС и сообщает ли об обнаруженных отклонениях?
  8. Проверяет ли инсталлятор возможность установки исходящих соединений?
  9. Проверяет ли инсталлятор значение критических для безопасности, производительности и общей работоспособности ПС параметров PHP, таких как register_globals, allow_url_fopen, post_max_size и т.п.?
  10. Показывает ли инсталлятор, какие шаги он собирается выполнить, выполняет, выполнил (с указанием результата выполнения)?
  11. Даёт ли инсталлятор рекомендации по устранению обнаруженных ошибок?
  12. Позволяет ли инсталлятор автоматизировать процесс устранения обнаруженных ошибок?
  13. Позволяет ли инсталлятор вернуться на предыдущий шаг (предыдущие шаги) инсталляции, внести изменения в параметры и продолжить инсталляцию с новыми параметрами?
  14. Учитывает ли инсталлятор следующие ситуации:
    1. новая среда исполнения, в которой приложение ранее не было инсталлировано;
    2. обновление существующей версии («апгрейд»);
    3. изменение текущей версии на более старую («даунгрейд»);
    4. повторная установка приложения с целью устранения возникших проблем («переинсталляция»);
    5. повторный запуск инсталляции после фатальной ошибки, приведшей к невозможности продолжения инсталляции;
    6. удаление приложения;
    7. установка нового приложения из семейства приложений (например, мы выпускам форум и блог);

Этот чек-лист, естественно, может быть расширен и уточнён. Например, пункт 1 можно расписать в такой набор идей тестов:

  1. POSITIVE Инсталлировать: а) скрипты в /users/htdocs/ex1/, б) файлы данных в /users/htdocs/ex1/data/; использовать БД: localhost:user1:passord1:database1
  2. POSITIVE Инсталлировать: а) скрипты в /users/htdocs/ex2/, б) файлы данных в /users/htdocs/ex2/data/; использовать БД: localhost:user2:passord2:database2
  3. POSITIVE Инсталлировать: а) скрипты в c:/www/pr1/, б) файлы данных в c:/www/pr1/dannye/; использовать БД: 127.0.0.1:user_1:passord_1:database_1
  4. POSITIVE Инсталлировать: а) скрипты в c:/www/pr2/, б) файлы данных в c:/www/pr2/dannye/; использовать БД: 127.0.0.1:user_2:passord_2:database_2
  5. NEGATIVE Инсталлировать: а) скрипты в /users/ex2/ (вне document root), б) файлы данных в /users/htdocs/ex2/data/; использовать БД: localhost:user2:passord2:database2
  6. NEGATIVE Инсталлировать: а) скрипты в /users/htdocs/ex2/, б) файлы данных в /users/ex2/data/ (вне document root); использовать БД: localhost:user2:passord2:database2
  7. NEGATIVE Инсталлировать: а) скрипты в /users/htdocs/ex2/, б) файлы данных в /users/htdocs/ex2/data/; использовать БД: www.google.com:user2:passord2:database2 (некорректный хост СУБД)

P.S. По тестированию «инсталляторов вообще» рекомендую эту прекрасную заметку.

Продолжение темы тестирования веб-ориентированных приложений — здесь.

Комментарии

  1. […] Продолжаем серию заметок о тестировании веб-ориентированных приложений, начатую здесь. […]

  2. […] Немного о таких проверках было говорено здесь. Теперь же мы поговорим о том, когда, зачем и как […]