Пользователь
0,0
рейтинг
18 января 2012 в 07:02

Разработка → Codeception — тестирование по-новому

PHP*
PHP очень популярный язык программирования, но тестирование в нем, это скорее прерогатива экспертов, а не жизненная необходимость. Неужели это от того, что PHP-разработчики поголовно быдло-кодеры? Я считаю, что нет. Скорее всё от того, что системы тестирования порой излишне усложнены. А тесты, наоборот, должны были предельно просты: легко читаться, писаться, отлаживаться, и конечно же, быстро выполняться. Мое виденье того как это можно воплотить в PHP вылилось в проект под названием Codeception.

С ним тесты для ваших веб-приложений могут выглядеть так:
<?php
$I = new TestGuy($scenario);
$I->wantTo('create new blog post');
$I->amOnPage('/blog/posts');
$I->click('Create new post');
$I->fillField('Title','Codeception, a new way of testing!');
$I->fillField('Text','Codeception is new PHP full-stack testing framework.');
$I->click('Send');
$I->see('Congratulations, your post is successfully created!');


Согласитесь, такой тест понятен без дополнительных комментариев.
А теперь самое интересное: этот код без всяких изменений может быть выполнен как функциональный тест в фреймворках symfony, Symfony2,Zend Framework, а также в браузерном эмуляторе Goutte и даже через Selenium. Таким образом, вам предлагается единый интерфейс для написания функциональных тестов практически для любого сайта.

В Codeception в максимально простой форме вы описываете весь тест в виде сценария. Вы повторяете действия пользователя, который использует ваше веб-приложение: кликает по ссылкам, заполняет формы и ожидает увидеть некоторый результат. Логично было бы написать тест, который бы в точности отражал его действия. При этом сам процесс написания теста крайне прост, если в своей IDE вы используете автодополнение:



Codeception работает на трех китах:
— как тестовая среда используется PHPUnit.
— для приемочных тестов — Mink. За него огромная благодарность Константину Кудряшову everzet.
— и конечно же, Symfony Components. Они используются практически для всего. Особо стоит отметить BrowserKit, который используется для функциональных тестов.

Чтобы начать, установите Codeception через PEAR:

$ pear channel-discover codeception.com/pear
$ pear install codeception/Codeception


Теперь установите необходимые зависимости.
$ codecept install


Выберите проект, который вы хотите тестировать и выполните в его корне команды

$ codecept bootstrap
$ codecept build


Команда «bootstrap» создаст конфигурационный файл и папку tests для трех категорий тестов:

— unit
— functional
— acceptance

Тут важно отметить, что мы различаем функциональные и приемочные тесты. Последние требуют наличие веб-сервера, на котором и будет проходить тестирование посредством того же Goutte или Selenium. Функциональные запускают приложение внутри самого теста, как это, например, происходит при тестирвоании в Symfony или Zend Framework.

Проще всего начать с написания приемочного теста. В каталоге tests/acceptance создадим новый файл StartPageCept.php:

<?php
$I = new WebGuy($scenario);
$I->wantToTest('front page of my site');
$I->amOnPage('/');
$I->see('A sample text on my site');


Он проверяет, что на главной странице вашего сайта есть текст: 'A sample text on my site'. Впишите в see текст, который там действительно есть, и ваш тест готов к прогонке.
Но прежде чем запустить его, вспомним, что приемочные тесты требуют, чтобы сайт выполнялся внутри веб-сервера. А значит необходимо сообщить url через который можно получить доступ к нашему сайту. Откроем файл: tests/acceptance.suite.yml

    config:
        PhpBrowser:
            url: 'тут мы впишем url к главке'


Теперь выполните.

$ codecept run acceptance


И увидите что-то типа такого:

Suite acceptance started
Trying to see front page of my site (StartPageCept) - Ok

Time: 1 second, Memory: 21.00Mb

OK (1 test, 1 assertions)


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

<?php
$I = new WebGuy($scenario);
$I->wantTo('log in as regular user');
$I->amOnPage('/login');
$I->fillField('Username','davert');
$I->fillField('Password','qwerty');
$I->click('Login');
$I->see('Hello, davert');
?>


Больше о написании тестов читайте в документации.

Чтобы выполнить один из этих тестов внутри фреймворка, следует скопировать тест в 'tests/functional', и отредактировать файл test/functional.suite.yml.
Приведу пример для Symfony2, но абсолютно аналогично вы можете подключить Zend Framework или symfony, а также Doctrine1 или Doctrine2.

class_name: TestGuy
modules:
    enabled: [Symfony2, TestHelper] 


Так мы указали модуль Symfony2 для использования в функциональных тестах. Если ваш AppKernel находится стандартно, в папке 'app', тест будет выполнен без дополнительной конфигурации.

Для запуска функциональных тестов следует использовать:
$ codecept run functional


Расскажу о модулях. В модулях определены действия, которые доступны при написании тестов. В классе описания сценариев TestGuy или WebGuy доступны методы взятые с нескольких модулей.
Модули также реализуют интеграцию с разными библиотеками практически без настройки и совершенно не требуют установки дополнительных плагинов или бандлов в ваше приложение.

Codeception не только выполняет тесты, но так же старается с нуля создать необходимую среду для тестирования. Важной частью тестирования является приготовление базы данных и её очистка.
Реализуется она посредством модуля Db. Создайте тестовую базу данных и заполните её данными, необходимыми для тестирования. Можно делать это вручную или используя фикстуры. Создайте дамп базы и поместите его в папку tests/_data. Затем откройте конфигурационный файл codeception.yml в корне вашего проекта и впишите для модуля Db параметры доступа к базе данных и путь к дампу. Теперь, если вы добавите модуль Db к списку модулей в файле tests/acceptance.suite.yml или functional.suite.yml, база данных будет обновляться автоматически после каждого теста.

Впрочем, это не единственный способ очистки. Если вы используете Doctrine или Doctrine2, то соответствующие модули помещают все ваши запросы в транзакцию и выполняют rollback в конце.
Таким образом база данных не засоряется, а значит и постоянная очистка ей не нужна. Такие тесты будут работать очень быстро, но транзакции доступны только в функциональных и юнит-тестах.

Более полную документацию вы найдете на официальном сайте. Там доступны как обзорные материалы, так и описания конкретных модулей.

Codeception сейчас находится в стадии бета-тестирования и ваши отзывы будут крайне желательны.
Следите за проектом на GitHub.
Davert @Davert
карма
111,8
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (67)

  • +8
    Кажется, я нашел тестировалку, о которой мечтал.
    • +5
      Вот она, вооот онааа, тестировалка моей мечты!!!
  • +12
    Супер! прям для дибилов меня, спасибо!
  • 0
    Это божественно!
  • 0
    Спасибо. Это должно упростить жизньработу.
    • 0
      выбирай одно из двух: жизнь или работу?
      или вся твоя жизнь — это одна большая работа??
      • 0
        Не не не. Только работу. Просто я забыл что у меня сейчас HTML в комментариях не работает :)
  • +1
    А что делать с drag&drop?
    • +2
      Если я правильно понимаю, это уже UI, основаный на js — тут уже отдельная методика и средства тестирования.
  • 0
    У меня к сожалению не завелось.
    1. Прочитал доки по установке на Вашем сайте.
    2. Установил пакет из pear.
    3. Запустил codecept install через sudo

    Все дальнейшие команды (codecept bootstrap, codecept buil, codecept run) не дают никаких результатов ни в пустой папке, ни в папке с каким либо проектом. Вообще команда codecept никак не реагирует ни на какие параметры, даже если ей передать произвольную строку.
    • 0
      Забыл сказать. Система kubuntu 11.10, PHP 5.3.6-13ubuntu3.3
    • 0
      phpUnit устанавливал вручную, т.к. команда install ругнулась на старую версию PEAR Installer.
      • 0
        ой. Старая версия PEAR Installer. Что не обходимо установить в виде pear пакетов: Mink и Symfony Components.
        Я постараюсь по-быстрому добавить возможность установки через Composer.
      • 0
        Пока советую обновить PEAR Installer. Танцы с бубнами, конечно, но пока это лучший способ.
      • 0
        pear upgrade PEAR
  • +3
    А планируется ли добавить класс TestGirl? )
    • +7
      А также TestBlond, который будет совершать действия, отличные от заданных в сценарии, и ожидать верного результата. :)
      • +6
        TestBlond нужно будет ещё прогонять через TestGuy чтобы удостовериться что оно работает )
        • 0
          дожили…
    • 0
      А по теме. Спасибо за работу. Единственный минус BDT, что покрыть все use case просто невозможно. Т.е. нет никакой гарантии что оно действительно работает.
      • 0
        Угу. Но могу ещё про юнит-тесты рассказать ) Они там тоже есть.
  • +1
    О нем рассказывали на конференции по Symfony в Украине. Это были не Вы случаем?
    • +1
      Тоже помню этот доклад. С того времени начал внедрять в свои проекты
    • 0
      Таки да. Только парней с тех пор развелось больше )
  • 0
    Это же просто праздник какой-то
  • 0
    Наконец-то для sf2 оформил :) жаль на симфоникамп не успел :)
    • 0
      Ой, я только недавно под symfony2 оформил. Что поделаешь — мало с ним работаю :( Но кстати, важно не то, что Symfony2 завелся, а то, что через BrowserKit есть универсальный доступ практически ко всем фреймворкам.
  • +3
    Советую еще всем, кому понравилось, посмотреть на BDD Framework Behat.
  • +2
    Вопрос к автору как раз на эту тему: можете сказать, какие плюсы и минусы есть у Codeception по сравнению с Behat?
    • 0
      По описанию принципиальных отличий или преимуществ Codeception по сравнению с Behat вроде бы нет. Похоже, что это тот же Behat, только в профиль.
    • +1
      Ну тут скорее дело привычки. И то и то сценарный BDD, но мне проще писать PHP-код, а не сочинения на тему «каким я вижу сайт».

      Ну а из принципиальных, behat занимается только приемочными тестами. Тут же вся инфраструктура, с модулями для чистки БД. Ну и наверняка, много отличий в мелочах. Например, Codeception автоматически сохраняет скриншот последней страницы, если тест не удался. Ну, или умеет эмулировать AJAX-запросы в режиме PHP-браузера. Все команды понимают как названия, так и CSS-селекторы…
      • 0
        Твой тул со сценарным BDD не имеет почти ничего общего, кроме понятия сценария. Почитай на досуге: dannorth.net/whats-in-a-story/
        • 0
          Не-не-не, на RubyC была отличная презенташка, где рассказывалось, что BDD это Beer Driven Development. Так что, в такой вот расшифровке, оно очень даже верно.

          А вообще, я использую термин, BDD не потому что он там уместен, а потому что так проще донести мысль. Может он и некорректен, но судя по всему, как ни крути, народ всё равно будет сравнивать с Behat.
          • 0
            … а behat будут называть фреймворком для функционального тестирования
          • 0
            Чтобы не было никаких претензий к терминологии:

            image

            image
    • +1
      Это 2 разные вещи. У автора — высокоуровневый тул для функционального тестирования. Behat — тул для тестирования бизнесс правил, описанных в виде поведенческих сценариев на языке, доступном для «непрограммистов».

      Корректнее сравнивать этот тул с PHPUnit/PHPSpec+Mink, потому как он имеет больше общего с функциональными спецификациями (Spec BDD, Unit tests), нежели поведенческими сценариями (Scenario BDD).
  • 0
    Ок, а как его прикрутить к continuous integration server (Jenkins, Hudson и иже с ними)? Если оно пользует PHPUnit (скорее всего его части asserts и профайлинга тестов) — как заставить его писать отчёты по покрытию тестами и т.д. в файлики?
    • 0
      Пока что я его прикрутил только к TravisCI.

      Насчет отчетов по покрытию тестами, я не совсем понял. Вы имеете ввиду, CodeCoverage? Если мы говорим о функциональных тестах, то они никогда не покроют код. А приемочные его даже дергать не будут.

      Из того что есть: генерация отчетов в виде HTML и в виде репортов.
  • +1
    Если уж решили взяться за написание тестов «человеческим языком», то почему бы не использовать Gherkin? Это, на мой взгляд, горяздо более наглядный и гибкий способ описания сценариев.
    • 0
      Вот-вот :) Получается, что Codeception это тот же Behat, только без поддержки Gherkin.
    • 0
      А зачем нам ещё один Behat? ;)
      Читаемый код это тоже человеческий язык. Хороший код читается без комментариев, а пишется быстрее текста. Например, через указанное автодополнение.

      Хотя смотря, конечно, кто будет читать ваши тесты. Если их будут читать разработчики + менеджеры, то Codeception они осилят (плюс можно перевести текст в нормальный english), если текст будут читать заказчики, то, конечно Behat лучше.

      Каждый тест можно ещё в таком виде представить:

      I WANT TO SIGN IN
      I am on page '/login'
      I fill field ['signin[username]', 'davert']
      I fill field ['signin[password]', 'qwerty']
      I click 'LOGIN'
      I see 'Welcome, Davert!'
  • 0
    Неужели это от того, что PHP-разработчики поголовно быдло-кодеры? Я считаю, что нет.
    Вы так говорите, будто согласны с тем что PHP-разработчики быдло кодеры, но не согласны что из-за этого приложения не тестируют.
    • 0
      Они не тестируют, ибо нет хороших простых инструментов:

      Что есть? «PHPUnit + Selenium». Буду ли я стрелять из пушки по воробьям, если, допустим, у меня небольшой сайт на друпале и мне совершенно не хочется заморачиваться в установке этих двух монстров. Человеку не привычному к PHPUnit настройка этой связки может трудной, а в итоге напрочь отобьет желание что-то тестировать. А самое глваное — нет необходимости гонять все тесты в Selenium.

      Тот же Behat+Mink намного лучше, но он, как мне кажется, всё равно пока больше для гиков.
      • 0
        А для других платформ, на Ваш взгляд, есть хорошие инструменты?
        • +1
          Ну, далеко не на всех платформах пишут сайты )

          А так, впринципе, то на Ruby, что RSpec, что TestUnit, что Cucumber — все они хороши. Из-за особенностей языка, его инфраструктуры и сообщества.

          Будем надеяться, что в PHP тулзы для тестирвоания будут развиваться.
        • 0
          В том же Ruby (on Rails), как выше уже написали, существует прекрасная связка Cucumber+Capybara+RSpec. и к оным существует over 9000 разнообразных примочек, чтобы жизнь тестера была похожа на сказку. В свое время, когда еще приходилось немного кодить на php, я был дико обрадован появлению Behat, т.к. уже тогда слабо себе представлял разработку без автоматизированного тестирования.
  • 0
    На первый взгляд не увидел преимуществ перед Behat и Mink. Добавьте, пожалуйста, сравнение, если этот инструмент действительно в чём-то лучше.
    • 0
      Ну см. комментарии выше. Но если вы уже используете Behat, то я не буду отговаривать вас )
  • 0
    Осталось прикрутить всё к Yii… :D
    • +1
      Попробуйте сначала с приемочных тестов — они универсальны.

      А если нужна тесная интеграция с Yii, то можете взять и интегрировать:
      codeception.com/docs/05-FunctionalTests#integrating-other-framwork

      Если будут вопросы, стучитесь в скайп: davert.ua
  • 0
    а на CodeIgniter заработает?
    • 0
      Опять таки, комментарий выше. Если тестировать с Goutte или в Selenium, оно обязательно заработает. Ну а список поддерживаемых фреймворков будет постепенно обновляться.
  • 0
    Приемочный тест не завелся на ZF

    Exception thrown Zend\Http\Exception\InvalidArgumentException:
    Invalid parameter type passed as Cookie

    Ткните мордой, что я не так делаю, пожалуйста.
    Mink ставил отдельно
    • 0
      Первое что стоит попробовать запустить с опцией --debug и показать stack trace.
  • 0
    сделал все по инструкции
    В ответ получаю

    There was 1 failure:

    Couldn't test front page of my site (StartPageCept.php)
    Method StartPageCept.php does not exist

    • 0
      Method? Так сходу сложно представить что не так.
      Может в скайпе обсудим?

      Мой: davert.ua
  • 0
    Ни у кого проблем с utf8 не возникало?

    Решил поиграть с codeception, но заметил интересную зависимость. Если передать в метод see() метку с национальными символами в utf-8, то всё работает правильно до момента пока вторым параметром не указать селектор области поиска.
    Пример:

    $I->see('Москва');

    > * I see «Москва»
    > OK

    $I->see('Москва', 'div');

    > 1. I see ["\u041c\u043e\u0441\u043a\u0432\u0430",«div»]
    >
    >FAILURES!
    • 0
      Если что, лучше создавать Issues в GitHub или в секции Q&A. А то этот топик скоро затеряется в дубрях Хабра )

      Я так подозреваю, вы приемочный тест писали? Вечером посмотрю в чем проблема.
      • 0
        Да, это приёмочный тест
  • 0
    Какой средой пользуется уважаемый автор? Спасибо за лаконичный инструмент, такого сильно не хватало.
    • 0
      То есть ОС? Сижу в Windows в ожидании Ubuntu 12 (громко скорбя над упавшим Оцелотом), тестю всё как в винде, так и в под виртуалкой в lubuntu.

      Codeception покрыт тестами. Они через CI-сервер гоняются под линуксом с использованием Selenium, MySQL, Sqlite и в PHP 5.3, 5.4.
    • 0
      Или IDE? Тогда PHPStorm
      Подозреваю, что в Netbeans, Eclipse разрабатывать будет так же удобно )
      • 0
        Да, я IDE имел в виду. Спасибо еще раз.
  • 0
    А могу я потестировать вебсервис с помощью Acceptance test? Например, постим данные на урл и ассертим json/лезем в бд.
    • 0
      Не поверите, недавно как раз добавил модули для REST и SOAP тестирования.
      Пока правда нету развернутых гайдов по их использованию, но уже достаточно документированы.

      codeception.com/06-19-2012/testing-webservices.html
  • 0
    Не могу найти инфу на тему как лучше сделать отдельный конфиг для теста / группы тестов.
    Можно конечно инклудить свой, но красивше было бы заюзать системный yml конфиг
    Не подскажете как доставать значения из yml в пространство теста?

    PS: использую только приемочные для тестирования REST сервисов
    • 0
      Пока никак. Но сейчас как раз усиленно думаю в этом направлении. Думаю, скоро, появится такая возможность.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.