» Главная
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.32 [Голосов 183]Кол-во просмотров: 14673

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

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

2016-11-30 17:49:22
svarkagid.com
TDD не только предполагает проверку корректности, но и влияет на дизайн программы. Опираясь на тесты, разработчики могут быстрее представить, какая функциональность необходима пользователю. Таким образом, детали интерфейса появляются задолго до окончательной реализации решения.

2016-07-19 01:39:30
ClyuchSmap
Сборник лицензий, для хитовых антивирусных программ: Аваст, Касперский, Dr.Web, Эсет Нод32, Avira, Нортон, Emsisoft, AVG, ТрастПорт, G Data, Bitdefender, Комодо, Аутпост, Panda: http://imgur.com/Z7Uf2Cc


<a href=http://imgur.com/T34Ytb8><img>http://keys-online.ru/wp-content/uploads/2015/03/51513544.jpg</img></a>

ключ активации для антивирус касперский 2014

2016-06-28 08:03:34
ClyuchSmap
Архив лицензий, для лучших антивирусных программ: Аваст, Kaspersky, Доктор.Веб, Эсет Нод32, Avira, Нортон, Emsisoft, AVG, TrustPort, G Data, Bitdefender, Comodo, Аутпост, Panda:

<a href=http://imgur.com/xegOBkx><img>http://preview.ucoz.ru/001/apteka/Antivirus.png</img></a>



2016-06-26 01:44:22
ClyuchSmap
Выборка лицензий, для хитовых антивирусных программ: Аваст, Kaspersky, Доктор.Веб, ESET NOD32, Авира, Norton, Emsisoft, AVG, ТрастПорт, Джи Дата, Битдефендер, Комодо, Аутпост, Панда: http://imgur.com/kQYpkSJ


<a href=http://imgur.com/606GEtw><img>http://netvirusu.net/wp-content/uploads/2014/11/kasperskiy-antivirus-logo.jpg</img></a>


сайт ключами для антивируса avast

2015-07-29 07:52:45
SegaSn
В целом хорошая приставка: http://bit.ly/emulyator-sega-2

<a href=http://bit.ly/sega-master-system><img>http://images.vfl.ru/ii/1437899400/283452f6/9390331.jpg</img></a>

sega universe

2015-07-29 04:25:36
SegaSn
В целом хорошая приставка: http://bit.ly/sega-master-system

<a href=http://bit.ly/games-sega-mega><img>http://images.vfl.ru/ii/1437903302/30bcc409/9390849.jpg</img></a>

sega x-perts

2012-12-26 14:25:38
viertaltmooro
Ищете, где купить канаты, канат текстильный?
Канат стальной просто необходим для такелажных и подъемных работ.
ООО Мегапром - предлагает купить канат авиационный на территории России.
Отгрузка из наличия со склада г.Орел. ж/д контейнером или автомобильным транспортом через любую транспортную компанию, в кратчайшие сроки в любую точку страны.
Возможна резка, отмотка. Вся продукция сертифицирована и имеет необходимые маркировки.

2012-07-12 01:59:43
OutrartbruddY
Добрый деньcДоброго времени суток!
Думаю приобрести крепеж высокопрочный. Кто может что-то посоветовать?
Какая фирма делает качественные высокопрочные крепежи?
Нашел вот на этом сайте: http://metizorel.ru/
Цены я думаю терпимые, но я в этом не спец, поэтому если покупали дешевле, покажите где. Где можно найти лучшее соотношение цена-качество?

2012-07-06 11:19:02
Ethictendoche
Ищете продажа электродов?
Компания Мегапром предлагает купить электроды гост от лучших производителей на территории России.
Электроды обеспечивют высокие механические свойства сварного соединения и высокую производительность процесса сварки.
Вся продукция сертифицирована и имеет необходимые маркировки.

2012-07-06 09:07:46
Ethictendoche
Ищете электроды уони?
Компания Мегапром предлагает купить электроды ок от лучших производителей на территории России.
Электроды обеспечивют высокие механические свойства сварного соединения и высокую производительность процесса сварки.
Вся продукция сертифицирована и имеет необходимые маркировки.
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Как вы относитесь к AJAX?
Считаю это ЗЛОМ
11% (12)
Бесполезная технология
2% (2)
Мне параллельно
9% (10)
Неплохая технология
20% (23)
Рулез, как я без нее жил!
7% (8)
Я разработчик AJAX-приложений
5% (6)
А что? Хороший футбольный клуб!
12% (14)
Я в танке!!!
34% (38)

Проголосовало: 113
Законы программизма от Ваще.
1. Ничто не работает так, как планировалось запрограммировать.
2. Ничто не программируется так, как должно работать.
3. Хороший программист характеризуется умением доказать почему задачу невозможно выполнить, когда ему просто лень её выполнять.
4. На решение проблемы уходит в три раза меньше времени, чем на обсуждение всех "за" и "против" её решения.
5. Обещанный срок сдачи - это аккуратно расчитанная дата окончания проекта плюс шесть месяцев.
6. Программисту всегда известна последовательность действий, которыми пользователь может повесить его программу, но он никогда не чинит эту проблему, надеясь на то, что никому никогда не придёт в голову эту последовательность исполнять.
7. Настоящие программисты любят Windows - все ошибки, сделанные по собственной тупости, можно свалить на Microsoft.
8. Следствие - 99% проблем, сваливаемых на Microsoft, является следствием тупости самих программистов.
9. В приступе злости все почему-то молотят по невинному монитору, вместо системного блока.
10. В случае голодовки настоящий программист ещё месяц сможет питатся едой, выковырянной из-под кнопок клавиатуры.
11. Настоящий программист уже как минимум поменял три залитых пивом клавиатуры.
12. Все, кто испытывает проблемы с настройкой кодировки, автоматически считаются неандертальцами.
13. Дилетантские разговоры о компьютерах вызывают резкую тошноту влоть до приступов рвоты. Вопрос о том как поменять "обои" в Windows вызывает желание перерезать горло вопрошающему.
14. У большинства людей, нуждающихся в твоей помощи, причина ошибки в работе программы чисто генетическая.
15. HTML, HTTP, FTP, SMTP, TCP/IP, RTFM и т.д. - это слова, а не аббревиатуры.
16. Словосочетание "мышка-норушка" не несёт никакого смысла.
17. Самые мистические проблемы, широко раздуваемые и афишируемые, в конце концов оказываются твоими глупейшими ошибками.
18. Следствие - если твоя программа выполняет мистические действия, значит, ты сделал что-то невероятно тупое.
19. Самое плохое ощущение для программиста - когда вокруг тебя стоят десять человек и все пытаются найти причину проблемы в твоей программе, а ты уже понял, в чём проблема, но боишься сказать, потому что это что-то вопиюще глупое...
20. Решение всех жизненных проблем находится на интернете. Надо только уметь хорошо искать.
21. Конфликт логических указаний в жизни вызывает фатальную ошибку в работе мозга программиста - возможно повышение температуры и сильное головокружение вплоть до рвоты или потери сознания.
22. Тех, кто презирает программистов, программисты презирают сильнее, чем те, кто презирает программистов, презирающих программистов, которые презирают тех, кто их презирает.
23. Если ты понял предыдущее - то ты программист.
Рейтинг: 0.5/10 (17)
Посмотреть все анекдоты