Простой инструмент для тестирования PHP приложений

    Для кого эта статья


    Скорее всего для тех, кто ещё не начал тестировать, но имеет такое желание. Опытных в этом деле разработчиков удивить не получится, но тех кто ещё не перешел на сторону света, попробую подтолкнуть на этот шаг.

    Предыстория


    Решил разобраться с автоматическим тестированием. Раньше этого делать не приходилось, да и тогда не было особо нужно. Зато было свободное время, которое решил потратить с пользой на будущее.
    Почитав теорию, начал искать инструмент для этого. Предсказуемо первым на горизонте показался PhpUnit. Но он показался каким-то громоздким, что ли.
    Более удобным показался Codeception — разные виды тестов, выразительный синтаксис. Но, посмотрев зависимости, я понял, что мне столько всего не нужно.
    Двигаясь в сторону простоты, я нашел atoum, а потом вообще классную вещь под названием Testify.php. Тут-то я подумал, что наконец нашел то, что мне нужно.

    Но я рано радовался. Testify.php не подошел при написании первого же теста. Тестировался класс кэширования, который в зависимости от того, включена отладка или нет, мог обрабатывать или игнорировать вызовы. Так как режим отладки предполагал наличие константы DEBUG со значением true/false — переопределить её в одном процессе не получится.

    Требования


    После этих поисков я понял, что нужен простой инструмент, который:
    • Будет тестировать в разных процессах, чтобы определять нужные константы, mock-ать одни и те же классы для разных тестов по разному, и т.д.
    • Будет максимально простым в использовании
    • Сможет работать как через браузер, так и с командной строки
    • Можно будет использовать вместе с Travis CI (консольный вариант — в случае успешного тестирования должен вернуть статус 0)

    Реализация


    Был написан небольшой скрипт, который открывал тесты по http, собирал результаты, и выдавал в презентабельном HTML виде. Для того, чтобы сделать аналогичным процесс тестирования и для консольного варианта — было решено использовать встроенный в PHP 5.4+ веб-сервер. Запускается он так:

    //Запуск
    $web_server_pid = exec("php -S localhost:$this->port >/dev/null 2>/dev/null & echo $!");
    //Тестирование
    //...
    //Остановка
    exec("kill $web_server_pid");
    

    И оно заработало как положено. Так, как аналогичного инструмента не нашел — решил оформить в виде самостоятельного composer пакета, добавил интерактивности (прогресс выполнения наборов тестов отображается в реальном времени как в HTML, так и в консольном варианте).

    Запуск тестов:

    // test.php
    require __DIR__.'/vendor/autoload.php';
    (new \nazarpc\CSTester(__DIR__.'/tests'))->run();
    

    Теперь этот файл можно открыть либо в браузере, либо в консоли

    php test.php
    

    Сами тесты не на много сложнее:

    return 5 != 3 ? 0 : 'Strange PHP';
    

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

    Пример результата консольного варианта:



    Есть возможность выполнить общие команды как перед всеми наборами тестов, так и перед всеми тестами одного набора.

    Уверен, что можно сделать еще лучше, поэтому жду конструктивной критики и предложений.
    Зависимостей никаких, голый PHP 5.4+ подойдёт.

    GitHub репозиторий: github.com/nazar-pc/CSTester
    Composer пакет: packagist.org/packages/nazar-pc/cstester
    • +6
    • 10,6k
    • 9
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 9
    • +4
      >Зависимостей никаких, голый PHP 5.4+ подойдёт.
      lol)
      кстати у Codeception есть 2 доп хороших либы(Verify, Specify), правда они еще не альфа наверное, но работают вроде :) Ну и выбирали вы как-то странно если честно, ну да ладно :)
      • +1
        Но, посмотрев зависимости, я понял, что мне столько всего не нужно.

        Тут вынужден согласиться. Зависимостей уже более чем дофига и возможно пора уже выносить что-то в отдельные пакеты.

        Но реальность такова, что самой главной зависимости — PHPUnit, пока нет альтернатив. На чуть более менее сложном проекте он должен быть. Не зря его называют «стандартом де факто» в тестировании. Возможно он черезмерно тяжел и раздут, но более менее серьезный проект разрабатывать без него не стоит.
        • +2
          Не понял, так чем PhpUnit не понравился?
          • 0
            Он слишком большой и избыточный для меня. По крайней мере для начала он мне не нужен. То, что в PHP это промышленный стандарт я даже не собираюсь спорить, но иногда нужны игрушки калибром по меньше, и в этом плане упомянутый Testify, либо мой вариант гораздо удобнее и интереснее, а самое главное — проще.
            fog, промазал.
            • 0
              Я не понял в чём его громоздкость. В объеме файлов, классов? Почему это помеха? Или в громоздкость кода? Но тут я тоже не понимаю :)
              • 0
                Это моё субъективное мнение после просмотра нескольких статей, многочисленных примеров и размера репозитория.
                Создавать отдельный класс и метод ради

                $this->assertTrue(...);
                

                я считаю избыточным, а более широкую функциональность (при том, что всё можно свести к предыдущей) мне и не нужно. Опять же, это не исключает изменения моего мнения со временем, и новыми обстоятельствами.
                • 0
                  Создавать отдельный класс и метод ради… я считаю избыточным

                  ну, не создавайте, пользуютесь функциями https://github.com/sebastianbergmann/phpunit/blob/master/PHPUnit/Framework/Assert/Functions.php

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

                  часто бывает, что сегодня не нужно, завтра не нужно, а после завтра — кровь из носа, как нужно.
                  • 0
                    Присмотритесь к стандартным PHPT-тестам, которыми покрыт сам код PHP. Они же идут по умолчанию вместе с PEAR. Это, правда, не юнит-тесты (для юнит-тестов ничего лучше phpUnit-а нет, только для phpUnit надо свой пускач написать, чтобы каждый раз не копипастить), но зато они просты, как три копейки, и работают каждый в отдельном процессе. Если нужно за час написать 20-30 дымовых тестов для какой-нибудь библиотеки или подсистемы — самое то.
                    • 0
                      Ну, размер репозитория меня мало беспокоит, собрал один раз всё в отдельную папку (в проект не входит) и забыл.

                      Создавать отдельный класс и метод ради… я считаю избыточным


                      Странно, куда как не в отдельный файл/класс вписать тест =)

                      более широкую функциональность мне и не нужно


                      Я тоже не использую все возможности UnitTest, но в целом их наличие меня не отягощает. :)

                      Спасибо за ответ.

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