Skip to content

Latest commit

 

History

History
411 lines (336 loc) · 22.5 KB

codeception.md

File metadata and controls

411 lines (336 loc) · 22.5 KB

Codeception и тестирование шаблонов yii2

Codeception: заметки о тестировании в docker.

Первое - подготовить Codeception для тестирования этого проекта. Взяв за основу codeception/codeception, создадим образ для запуска тестов с установленными дополнительными модулями.

bscheshir/codeception:php-fpm-yii2

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

Копируем, например, из запущеного контейнера, средствами docker

rm -Rf ~/projects/.codecept
docker cp docker-codeception-run_codecept_run_1:/repo/ ~/projects/.codecept

Для отладки тестов В PHPStorm настроить следующее: Добавить сервер с указанным в перемнной PHP_IDE_CONFIG именем Settings > Languages & Frameworks > PHP > Servers: [Name => codeceptiom] В нём изменить path mapping. Settings > Languages & Frameworks > PHP > Servers: [Use path mapping => True, /home/user/yourprojectname/.codecept => /repo, /home/user/yourprojectname/php-data => /project] Изменить порт по умолчанию 9000 на используемый в настройках Settings > Languages & Frameworks > PHP > Debug: [Debug port => 9002]

Для запущенных случаев (например, возможных проверок фиксов самого фреймворка тестирования) справедливо обратное копирование

docker cp .codecept/src/Codeception/Lib/Connector/Yii2.php dockercodeceptionrun_codecept_run_1:/repo/src/Codeception/Lib/Connector/Yii2.php
docker cp .codecept/src/Codeception/Module/Yii2.php dockercodeceptionrun_codecept_run_1:/repo/src/Codeception/Module/Yii2.php

Тонкая настройка окружения и точечные изменения

Для возможности запуска selenium из той же сети, созданной docker - в созданных командой init локальных точках входа тестов php-data/backend/web/index-test.php, php-data/frontend/web/index-test.php нужно изменить проверку IP

//check if not in same subnet /16 (255.255.0.0)
if ((ip2long(@$_SERVER['REMOTE_ADDR']) ^ ip2long(@$_SERVER['SERVER_ADDR'])) >= 2 ** 16) {
    die('You are not allowed to access this file.');
}

Также изменен принцип подключения к тестовой базе - используется одинаковое имя базы, но при подключении сервис db будет переключён на другую дирректорию mysql-data-test - следовательно в настройках переопределение подключения избыточно. common/config/test-local.php

    [
        'components' => [
            'db' => [
                // Uncomment this line if your run Codeception test without Docker
                // 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test',
            ]
        ],
    ]

Для тестирования отправки почты необходимы права на запись в /var/www/html/[backend|frontend]/runtime/mail/ из контейнера. Т.е chmod o+rwx ./php-data/backend/runtime/mail, chmod o+rwx ./php-data/frontend/runtime/mail

Важен порядок подключения модулей Codeception: DbYii2Config c populate/cleanup ранее Yii2

        - \bscheshirwork\Codeception\Module\DbYii2Config:
            dump: ../common/tests/_data/dump.sql #relative path from "codeception.yml"
            populate: true
            cleanup: true
        - Yii2

Для детального анализа можно почистить директории вывода перед запуском

for i in frontend backend; do sudo rm php-data/$i/tests/_output/$i.tests.* php-data/$i/tests/_output/debug/* php-data/$i/tests/_output/failed; done

Запуск оболочки в контейнере Codeception

docker-compose -f docker-codeception-run/docker-compose.yml run --rm --entrypoint bash codecept

Обновление базы после добавления новых миграций

1.Остановить композицию, удалить текущую базу

docker-compose -f ~/projects/crm/docker-codeception-run/docker-compose.yml down
sudo rm -Rf ~/projects/crm/mysql-data-test/*

2.Запустить композицию, загрузить в вновьсозданную базу дамп

docker-compose -f ~/projects/crm/docker-codeception-run/docker-compose.yml up -d
time -p docker exec -i dockercodeceptionrun_db_1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" --database=crm' < ~/projects/crm/php-data/common/tests/_data/dump.sql

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

docker-compose -f ~/projects/crm/docker-codeception-run/docker-compose.yml exec php ./yii migrate/up

4.Сохранить новый дамп, проверить, закоммитить/откатить.

docker exec dockercodeceptionrun_db_1 sh -c 'exec mysqldump crm -uroot -p"$MYSQL_ROOT_PASSWORD" 2>/dev/null'>~/projects/crm/php-data/common/tests/_data/dump.sql

Покрытие кода тестами и c3.php

Настройки для acceptance тестов

Замечание для acceptance тестов: необходим c3.php, который требует установки Codeception в зависимостях. что вызввает необходимость дублировать код фреймворка тестирования.
Остальные типы тестов позволяют использовать проверку покрытия не устанавливая зависимость в composer.json кода, оставляя всю работу с тестами в контейнере сервиса тестов codecept

Точка входа для тестов php-data/backend|frontend/web/index-test.php должна быть дополнена c3.php для определения покрытия при работе с различными контейнерами для кода и для веб-сервера

// Codeception testing routes
if (file_exists(__DIR__ . '/../../c3.php')) {
    define('C3_CODECOVERAGE_ERROR_LOG_FILE',
        __DIR__ . '/runtime/c3_error.log'); //Optional (if not set the default c3 output dir will be used)
    define('C3_CODECEPTION_CONFIG_PATH',
        __DIR__ . '/tests'); //Optional (if not set the default c3 output dir will be used)
    require_once __DIR__ . '/../../c3.php';
}

При этом c3.php расположен в php-data/ и общий для frontend и backend групп тестов.

cd php-data/
rm c3.php codecept.phar
wget https://raw.githubusercontent.com/Codeception/c3/2.4.0/c3.php
wget http://codeception.com/codecept.phar

codecept.phar использован, дабы не плодить мусор в вендорах (чего хотелось, до последнего, избежать) это позоволяет не трогать composer.json в секции require-dev. Минус - ручное обновление и медленное обновление в источнике.

Можно заметить, что при сборе данных о покрытии с помощью c3.php используется Codeception из codecept.phar и выполняется код внутри контейнера сервиса php. Который отличался от контейнера сервиса codecept "точкой монтирования" php-data. Это не позволяло Codeception смешать результаты покрытия: например, из /var/www/html/frontend/models/ContactForm.php и /project/frontend/models/ContactForm.php брался только существующий в codecept путь /project/... Установка workdir сервиса codecept в /var/www/html/ решило проблему.

Настройки "удалённого тестирования" включают в себя c3_url (опционально) и remote_config (обязательно)

Необходим полный доступ к папкам отчётов. Задайте его, если возникают соответствующие проблемы.

sudo chmod -R go+rw php-data/frontend/tests/_output php-data/backend/tests/_output php-data/common/tests/_output

Настройки групп тестов отличаются портом php-data/backend/tests/acceptance.suite.yml

        - WebDriver:
            url: http://nginx:8081/
            host: browser
            port: 4444
            browser: chrome

php-data/frontend/tests/acceptance.suite.yml

        - WebDriver:
            url: http://nginx:8080/
            host: browser
            port: 4444
            browser: chrome

соответствующий путь будет передан в c3_url (последнюю настройку возможно установить напрямую)

Общие настройки

Настройки php-data/codeception.yml дополняются слеюующим

coverage:
    enabled: true

Кроме уже обозначенных (а также ещё раз напоминая о remote_config)

Обязательно необходимы огранчения покрытия Обязательно необходимы указания "удалённых" конфигов

php-data/backend/codeception.yml дополнятся следующим

coverage:
    # from nginx-conf-test/nginx.conf
    c3_url: http://nginx:8081/index-test.php
    # redefine `php-data/codeception.yml` for `c3.php`. Relative to `c3.php` dir:
    remote_config: backend/codeception.yml
    enabled: true
    include:
        - models/*
        - controllers/*
    exclude:
        - assets/*
        - config/*
        - runtime/*
        - views/*
        - web/*
        - tests/*

php-data/frontend/codeception.yml дополнятся следующим

coverage:
    # from nginx-conf-test/nginx.conf
    c3_url: http://nginx:8080/index-test.php
    # redefine `php-data/codeception.yml` for `c3.php`. Relative to `c3.php` dir:
    remote_config: frontend/codeception.yml
    enabled: true
    include:
        - models/*
        - controllers/*
    exclude:
        - assets/*
        - config/*
        - runtime/*
        - views/*
        - web/*
        - tests/*

Запуск тестов с покрытием кода

codecept run --coverage --coverage-xml --coverage-html

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

paths:
    log: console/runtime/logs

Зависимости шаблона yii2-app-advanced в части require-dev конфига composer.json вызывают конфликты версий Codeception

Codeception и Docker-инструменты PHPStorm

Вдохновившись заметкой про использоване PHPUnit
И написав про тестирование для модулей yii2
Решил проверить как обстоят дела с Codeception в данной IDE.

Делаем всё по аналогии:

  1. Создать интерпретатор на основании композиции докера, выбрав в настройках (File->Settings...) Languages & Frameworks, главную ветку PHP (не раворачивая), на этой странице кликните кнопку […] после выпадающего списка CLI interpreter. После чего нажмите зелёный плюс [+] и выбирать удалённый (From Docker, Vagrat, VM, Remote). default

На данной странице следует выберать Docker-compose и файл композиции для Codeception (не тот, что стоит по умолчанию) ./docker-codeception-run/docker-compose.yml - также используя меню [...] и сделав его единственной строчкой с помощью соответствующих инструментов [+][-]
Сервис, который нас интересует, это codecept. Примерное состояние настроек после применения перечисленного: default
После подтверждения всех изменений данного шага переходим к следующему.

  1. Далее в опциях (File->Settings...) находим фреймворки тестирования Languages & Frameworks, PHP ветка Test Frameworks
    В ней добавляем Codeception by remote interpreter, используя кнопку зелёного плюса [+] и выпадающее меню.
    default
    Указываем тип, созданный в предыдущем пункте: default
    Важно! Указываем путь ВНУТРИ контейнера к тому месту, где находится исполнимый файл codecept. Для используемого образа этот путь равен /repo/codecept. Убежаемся в этом, нажав кнопку со стрелочками после строки ввода.

Применяем изменения и возвращаемся в главное окно IDE.

  1. Настройка запуска осуществляется через меню (Run->Edit configurations...)
    Вы можете добавить новую конфигурацию используя кнопку плюс [+] и выбрав Codeception.
    default

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

default

Применяем изменения и возвращаемся в главное окно IDE.

  1. Опционально: если приложение на шаблоне yii2-advanced не было запущено в docker-compose, неоходимо загрузить зависимости, инициализировать и настроить приложение как Development, см.установку
    docker-compose -f docker-codeception-run/docker-compose.yml run --rm php composer update
    docker-compose -f docker-codeception-run/docker-compose.yml run --rm php ./init

  2. Запустить тесты с этого момента можно с помощью соответствующей кнопки с зелёным треугольником. Поздравляю!
    Вот только прибератся после этого придётся вручную - зависимости сервисов тянут и оставляют запущенные контейнеры.
    docker-compose -f docker-codeception-run/docker-compose.yml down Отладку тестов, по прежнему, лучше использовать запуская из командной строки - карта не сделана на созданный PHPstormом контейнер. Останов первой строки происходит на скрипте codeception.php

  3. Дополнительно можно создать отдельные конфигурации для запуска наборов тестов по отдельности, в 3м пункте выбрав соответствующий файл для frontend: php-data/frontend/codeception.yml. Также строчой ниже, в опциях, можно указать набор тестов, например functional.
    default
    Для остальных вариантов настройки аналогичны.

Отличия запуска в IDE от запуска в контейнере из командной строки

Внимание! В этом разделе указаны текущие проблемы тестирования и заплатка.

Заплатка устарела с выходом phpstorm_helpers:PS-181.4203.565, файл был изменён до такой степени, что переопределять нечего.

Всё отлично, казалось бы, и должно быть одинаково - но нет. Тесты, завершающиеся успехом при запуске контейнера codecept из командной строки

docker-compose -f docker-codeception-run/docker-compose.yml run --rm codecept run
...
Time: 1.59 minutes, Memory: 62.00MB

OK (26 tests, 127 assertions)

при запуске из PHPStorm в некоторых случаях провалиоись. Видимо, контейнер, создаваемый IDE изменён (например, в части пользователей) Также, что интерестно, IDE показывает другое количество тестов, а именно: 344 tests done: 14 failed - 1m 12s 730ms в строке прогресса и

FAILURES!
Tests: 26, Assertions: 74, Failures: 14.

В выводе результатов.
Все ошибки появились в наборах тестов functional

Отличие проявляется в обработке flash сообщений виджета Alert - при запуске из IDE Yii::$app->session->getAllFlashes() возвращает пустой массив. Также нашлась причина

session_start(): Cannot send session cache limiter - headers already sent (output started at /repo/vendor/phpunit/phpunit/src/Util/Printer.php:110)

Для трассировки скопируем также содержимое рабочей папки образа-помощника PHPStorm и укажем в карте

phpstorm_helpers:PS-173.4674.45

Копируем, например, из запущеного контейнера, средствами docker

rm -Rf ~/projects/.phpstorm_helpers
docker cp phpstorm_helpers_PS-173.4674.45:/opt/.phpstorm_helpers/ ~/projects/.phpstorm_helpers

Реультатом поиска и отладки стал неутешительный вывод - реализация codeception.php На данный момент сломана.

Переопределив в данном файле класс

...
/**
 * For avoid set headers before session start
 * Class PhpStorm_Codeception_ReportPrinter_Redefine
 */
class PhpStorm_Codeception_ReportPrinter_Redefine extends PHPUnit_TextUI_ResultPrinter
{
    /**
     * @inheritDoc
     */
    public function __construct(
        $out = null,
        $verbose = false,
        $colors = self::COLOR_DEFAULT,
        $debug = false,
        $numberOfColumns = 80,
        $reverse = false
    ) {
        parent::__construct(STDOUT, $verbose, $colors, $debug, $numberOfColumns, $reverse);
    }

    /**
     * Flush buffer and close output if it's not to a STDOUT stream
     */
    public function flush()
    {
        if ($this->out != STDOUT) {
            parent::flush();
        }
    }
}

class PhpStorm_Codeception_ReportPrinter extends PhpStorm_Codeception_ReportPrinter_Redefine
{
...

и удалив все старые контейнеры, которые могли закешировать его реализацию (я говорю о тебе, Reflection в Codeception), можно в папке .phpstorm_helpers запустить билд образа.

cd ~/projects/.phpstorm_helpers/
docker build --no-cache --pull -t phpstorm_helpers:PS-173.4674.45 .

Дальнейший запуск тестов пройдёт успешно. До следующего обновления.
531 tests done - 1m 18s 6900ms

Testing started at 12:56 ...
Codeception PHP Testing Framework v2.3.5
Powered by PHPUnit 5.7.21 by Sebastian Bergmann and contributors.


[common\tests]: tests from /var/www/html/common



[frontend\tests]: tests from /var/www/html//frontend



[backend\tests]: tests from /var/www/html/backend



Time: 1.57 minutes, Memory: 62.00MB

OK (26 tests, 127 assertions)

Process finished with exit code 0