» Главная
eXcode.ru » Статьи » PHP » Трюки
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 6





Tdd: Шаг первый - функциональные тесты




Шаг первый - функциональные тесты

План действий

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

  • используем SimpleTest (версия 1.0, http://simpletest.sourceforge.net) в качестве среды для функционального и модульного тестирования.
  • используем WACT (версия 0.2alpha, http://wact.sourceforge.net) в качестве шаблонной системы и в качестве DBAL(Database Abstraction Layer)
  • используем PHPMailer (версия 1.73, http://phpmailer.sourceforge.net) для формирования уведомлений по электронной почте

Все внешние библиотеки будем хранить в директории /external нашего приложения.

Функциональное тестирование

Наша задача - обезопасить функциональность приложения от будущих изменений, то есть мы должны гарантировать, что все наши будущие рефакторинги не приведут к тому, что мы потеряем часть его фукциональности приложения. Для этого существуют функциональные тесты. Для создания функциональных тестов мы будем использовать входящую в SimpleTest подсистему WebTester. Подробную информацию можно получить:

WEB тестирование при помощи SimpleTest

Работа с библиотекой SimpleTest при web тестировании определенным образом напоминает работу непосредственно с браузером. WebTester по сути предоставляет удобные методы, эмулирующие браузер, а именно:

  • получение страниц по адресу
  • навигирование по ссылкам и кнопкам
  • заполнение и отправление форм
  • организация непосредственных GET, POST, HEAD запросов
  • эмуляция фреймов
  • формирование HTTP заголовков
  • установка и модификация cookies

Кроме этого WebTester позволяет посмотреть на запрос «изнутри»:

  • вывести на экран дамп данных запроса
  • отобразить HTTP заголовки
  • показать исходный код полученной страницы

И конечно же, самой главной особенностью WebTester является способность проверить полученные в процессе браузинга результаты, вот лишь некоторые возможности:

  • сравнить контент страницы на предмет совпадения с некоторым регулярным выражением
  • проверить содержимое <title> тега
  • проверить наличие ссылок и их содержимого
  • удостовериться в правильности содержимого полей формы
  • проверить cookie на содержимое
  • проверить HTTP заголовки

Для всего вышеописанного WebTester предоставляет исключительно чистые и понятные интерфейсы, превращающие работу с ним в удовольствие, и скоро в этом убедитесь.

Вводим функциональные WEB тесты для нашего приложения

Подготавливаем тестовую среду

Для начала создадим директорию /tests, в которой будут располагаться все тесты для нашего приложения. В этой директории создадим файл runtests.php следующего содержания:

<?php
require_once(dirname(__FILE__) . '/setup.php');
 
class AllTests extends GroupTest {
    function AllTests() {
        $this->GroupTest('All tests for feedback project');
        $this->addTestFile('acceptance_tests.php');
    }
}
 
$test =& new AllTests();
if (SimpleReporter::inCli()) {
    exit ($test->run(new TextReporter()) ? 0 : 1);
}
 
$test->run(new HtmlReporter());
?>

Этот скрипт будет точкой входа для всех тестов, причем его можно запускать как из консоли, так и из браузера. Для работы этого скрипта нам также потребуются файлы setup.php и acceptance_tests.php. В setup.php мы будем хранить глобальные настройки для всех тестов. Пока мы в нем только подключаем библиотеку SimpleTest и определяем адрес web хоста с приложением:

<?php
 
define('SIMPLE_TEST', dirname(__FILE__) . '/../external/simpletest/');
define('FEEDBACK_PROJECT_HOST', 'http://localhost/feedback/');
 
if (!file_exists(SIMPLE_TEST . '/browser.php')) {
  die ('Make sure the SIMPLE_TEST constant is set correctly in this file(' . SIMPLE_TEST . ')');
}
 
require_once(SIMPLE_TEST . '/web_tester.php');
require_once(SIMPLE_TEST . '/reporter.php');
require_once(SIMPLE_TEST . '/unit_tester.php');
require_once(SIMPLE_TEST . '/mock_objects.php'); 
?>

Первые тесты

В acceptance_tests.php будут располагаться все функциональные тесты для приложения. Не долго раздумывая, поместим в него самый первый тест:

<?php
class AcceptanceTestOfFeedbackProject extends WebTestCase {
    function testOfIndexPage() {
        $this->get(FEEDBACK_PROJECT_HOST);
        $this->assertWantedPattern('/Обратная связь/');
    } 
 ?>

Суть данного теста сводится к посещения главной страницы нашего приложения и удостоверению, что страница содержит текст «Обратная связь». Допустим, что этот тест сработал, теперь можно перейти к более сложному тесту, целью которого будет проверка правильности отправки формы. Однако мы помним, что приложение сейчас работает с продукционной базой данных, что крайне опасно!!! Нам необходимо некоторым образом заставить приложение работать с другими настройками БД - тестовыми. К счастью, оригинальные разработчики решили хранить конфигурационные данные в отдельном файле db.php, который подключается в index.php. Мы можем на время тестов заменять db.php другим файлом, в котором находятся тестовые настройки. Но как это сделать лучше всего?

Устанавливаем фикстуру

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

SimpleTest позволяет подготовить некоторую окружающую среду для каждого тестового прецедента. Такая окружающая среда называется фикстурой(fixture). Сделать это можно при помощи методов setUp() и tearDown(). Эти методы вызываются соответсвенно до и после каждого тестового метода, что дает возможность разработчику произвести определенные подготавливающие мероприятия(очистка/заполнение БД, удаление временных файлов и проч).

Как упоминалось ранее, сделам так, чтобы на время тестов настройки базы данных подменивались тестовыми значениями. Для этого в директории tests создадим файл db.php - аналог того, который находится в корне приложения.

<?php
$db_host =      'localhost';
$db_name =      'feedback-web-tests';
$db_user =      'root';
$db_password =  'test';
?>

Теперь напишем фикстуру, подменяющую эти файлы перед каждым тестовым прецедентом. Также заставим фикстуру полностью очищать таблицу feedback, чтобы каждый тестовый прецедент имел «чистую» окружающую среду.

<?php
class AcceptanceTestOfFeedbackProject extends WebTestCase {
[...]
    function setUp() {
        $this->_switchToWebTestingDb();
    }
 
    function tearDown() {
        $this->_switchToProductionDb();
    }
 
    function _switchToWebTestingDb() {
        $project_dir = dirname(__FILE__) . '/../';
        $tests_dir = dirname(__FILE__) . '/';
 
        include($tests_dir . 'db.php');
        $conn = mysql_connect($db_host, $db_user, $db_password);
        mysql_select_db($db_name, $conn);
        mysql_query('DELETE FROM feedback', $conn);
 
        rename($project_dir . 'db.php', $project_dir . 'db.php~');
        copy($tests_dir . 'db.php', $project_dir . 'db.php');
    }
 
    function _switchToProductionDb() {
        $project_dir = dirname(__FILE__) . '/../';
        unlink($project_dir . 'db.php');
        rename($project_dir . 'db.php~', $project_dir . 'db.php');
    }
}
?>

Теперь когда наша продукционная база данных защищена от фатальных последствий можно приступать к тестирования отправки новых сообщений с формы.

Тестируем отправку данных с формы

Итак, тестовый случай будет выглядеть так:

<?php
class AcceptanceTestOfFeedbackProject extends WebTestCase {
[...]
    function testOfSimpleSubmitFeedback() {
        $this->_addFeedback($name = 'Bobby',
                            $email = 'email@dot.com',
                            $message = "This a message with `non-escaped characters`");
 
        $this->assertWantedPattern('/' . preg_quote($email) . '.*' .
                                         $name . '.*' .
                                         $message . '/s');
    }
 
    function _addFeedback($name, $email, $message) {
        $this->get(FEEDBACK_PROJECT_HOST);
        $this->setField('name', $name);
        $this->setField('email', $email);
        $this->setField('message', $message);
        $this->clickSubmitByName('submit');
        sleep(1);
    }
}
?>

Как вы успели заметить, мы также добавили внутренний метод, _addFeedback, который заполняет поля формы и отсылает ее. Этот метод окажется весьма кстати в последующих тестах. Постоянный рефакторинг тестов - не менее важная задача, чем рефакторинг тестируемого кода. Чтобы избежать ситуации когда у нас может быть несколько сообщений, пришедших в одно и то же время, мы принуждаем PHP «засыпать» на 1 секунду после добавления каждого сообщения.

Этот тест также успешно срабатывает.

Более сложные тесты

Добавим метод, проверяющий, что при выводе сообщения обрабатываюся на предмет небезопасных символов и тегов.

<?php
class AcceptanceTestOfFeedbackProject extends WebTestCase {
[...]
    function testOfEscapingUserInput() {
        $this->_addFeedback('<script>',
                            '<br>',
                            '"\'');
 
        $this->assertWantedPattern("/&lt;br&gt;.*&lt;script&gt;.*\\\&quot;\\\&#039;/s");
    }
}
?>

Теперь напишем тест, проверяющий правильность работы пейджера при добавлении нескольких сообщений:

<?php
class AcceptanceTestOfFeedbackProject extends WebTestCase {
[...]
    function testOfPager() {
        $this->get(FEEDBACK_PROJECT_HOST);
        $this->assertNoLink("<");
        $this->assertNoLink(">");
 
        for($i=1; $i<8; $i++) {
            $this->_addFeedback('Robot' . $i,
                                'robot' . $i . '@usrobotics.com',
                                'Hello i am Robot' . $i);
        }
 
        $this->get(FEEDBACK_PROJECT_HOST);
        $this->assertWantedPattern('/Robot7.*Robot6.*Robot5/s');
        $this->assertNoLink("<");
        $this->assertLink(">");
 
        $this->clickLink(">");
        $this->assertWantedPattern('/Robot4.*Robot3.*Robot2/s');
        $this->assertLink("<");
        $this->assertLink(">");
 
        $this->clickLink(">");
        $this->assertWantedPattern('/Robot1/');
        $this->assertLink("<");
        $this->assertNoLink(">");
 
        $this->clickLink("<");
        $this->assertWantedPattern('/Robot4.*Robot3.*Robot2/s');
        $this->assertLink("<");
        $this->assertLink(">");
 
        $this->clickLink("<");
        $this->assertWantedPattern('/Robot7.*Robot6.*Robot5/s');
        $this->assertNoLink("<");
        $this->assertLink(">");
    }
}
?>

Пейджер выводит по 3 сообщения, поэтому мы добавляем в тесте 8 сообщений, чтобы проверить граничные ситуации. В этом тесте мы также воспользовались методом clickLink класса WebTestCase, который позволяет проэмулировать навигирование пользователся по ссылкам.

Эти тесты покрывают весь функционал приложения, поэтому, убедившись в том, что все работает, мы приступаем к долгожданному рефакторингу приложения.

Далее - Шаг второй - отделяем бизнес логику от презентационной логики .

К началу статьи





Добавил: Дата публикации: 2008-03-04 11:05:22

Рейтинг статьи:0.00 [Голосов 0]Кол-во просмотров: 5010
Оцените статью:

Комментарии читателей

Всего комментариев: 22

2010-04-19 13:21:51
erundergo
Рабица - почему так называется металлическая сетка?
Почему металическая сетка называется - рабица?
Почему металическая сетка называется - рабица?
Никогда не задумывались над этим вопросом?
Если нет то восполняем пробелы и при случае даже можно блеснуть своими познаниями.
Такое имя <a href="http://www.orelsetka.ru">сетка</a> получила от своего конструктора Карла Рабица.
Это немецкий инженер, который придумал её для укрепления оштукатуренных поверхностей.
Ячейки рабицы имеют ромбовидную форму. После изобретения, рабица стала достаточно известной но своей основной цели не потеряла.
Её и сейчас используют для армирования кладки, фундамента, изоляции теплотрасс, а кроме это находят ещё массу областей для применения, в частности изготовления заборов, вольеров, клеток и многого другого.
Для крепости и долговечности, сетку делают из стальной проволоки с покрытием полимерным составом.

2010-04-18 19:42:17
Fettantunfamb
Арматурные сетки изготавливаются строго по ГОСТ на специальном сварочном оборудовании
из арматурной проволоки, расположенной в двух взаимно перпендикулярных направлениях и соединенной
в местах пересечения точечной сваркой. Крестообразное соединение стержней осуществляется в соответствии
с требованиями ГОСТ 14098-85. <a href="http://www.orelsetka.ru/setkaarm.html">Сетка арматурная</a>
в рулонах продается по доступной цене в компании Мегапром.

2010-04-18 01:29:40
Pishesque
Здравствуйте!
Думаю взять сетку рабица. Кто может что-нибуть посоветовать?
Какая фирма собирает надежные сетки - сетка рабица?
Видел вот на этом сайте: http://metizorel.ru
Цены по-моему умеренные, но я не уверен, поэтому если видели дешевле, покажите где. Где можно найти лучшее соотношение цена-качество?

2010-04-17 06:56:06
Excicicerwric
Привет!
Хочу приобрести сварную сетку. Кто может что-нибуть посоветовать?
Какая фирма делает качественные сетки сварные?
Смотрел вот на этом сайте: http://metizorel.ru
Цены по-моему невысокие, но я не очень разбираюсь, поэтому если находили дешевле, посоветуйте где. Где можно найти оптимальное соотношение цена-качество?

2010-04-16 03:13:10
hautbaxia
Наша компания предлагает сетку штукатурную производства Северсталь метиз ОСПАЗ со склада
г.Орел. В наличии огромный ассортимент сетки штукатурной.
Вы можете купить штукатурную сетку светлую и оцинкованную.
У нас всегда в наличии огромный выбор сетки штукатурной, цены от производителя.
Продажа сетки штукатурной оптом и в розницу со склада г.Орел.

2010-04-15 01:52:52
mopsowell
Наша компания предлагает гайки резьбовые по ГОСТ 5915 производства Северсталь метиз ОСПАЗ со склада г.Орел. В наличии огромный ассортимент гаек.
Вы можете купить гайки резьбовые по ГОСТ 5915. У нас всегда в наличии огромный выбор гаек: гайка резьбовая, цены от производителя.
Продажа гаек оптом и в розницу со склада г.Орел.

2010-04-14 00:39:31
Incortini
Добрый день!
Хочу приобрести шпильки резьбовые. Кто может что-нибуть посоветовать?
Какая фирма изготавливает надежные шпильки?
Находил вот на этом сайте: http://metizorel.ru/
Цены по-моему умеренные, но сомневаюсь, поэтому если находили дешевле, скажите где. Где можно найти лучшее соотношение цена-качество?

2010-04-12 02:48:02
hadaChowl
Добрый день!
Думаю купить электроды. Кто может что-то посоветовать?
Какая фирма изготавливает качественные электроды?
Видел вот на этом сайте: http://metizorel.ru/ Цены по-моему терпимые, но я не уверен, поэтому если видели дешевле, посоветуйте где. Где можно найти оптимальное соотношение цена-качество?

2010-04-11 09:55:17
apparaoutlilm
Ищете, где купить электроды, электроды сварочные, электроды УОНИ, электроды МР-3 или МР-3М (синие)?
Компания ООО Мегапром - курпный поставщик электродов от лучших производителей на территории России.
Вся продукция сертифицирована и имеет необходимые маркировки.

2010-04-10 17:07:13
loutlebal
Наша компания предлагает вязальную отоженную проволоку д.1.2 мм т/о ГОСТ 3282 производства
Северсталь метиз ОСПАЗ со склада г.Орел - проволока вязальная в мотках по 80-100 кг.
В наличии огромный ассортимент вязальной проволоки.
Вы можете купить вязальную проволоку светлую и оцинкованную.
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Какой марки ваш мобильник?
Nokia
40% (146)
Samsung
8% (28)
Siemens
16% (59)
Motorola
13% (49)
Sony Ericsson
13% (49)
LG
1% (4)
Pantech
0% (0)
Alcatel
2% (6)
Другой
3% (10)
Нет у меня мобилы
4% (15)

Проголосовало: 366
Интересно, у владельцев компьютера, выражение "мать его..." это ругательное?
Рейтинг: 0/10 (0)
Посмотреть все анекдоты

 
eXcode.ru » Статьи » PHP » Трюки