Сервис на Yii2: Тестирование приложения с Codeception

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

Предыдущие части | Исходники на GitHub | Скринкаст о тестировании

Приятно при написании кода время от времени запускать автотесты и наблюдать, что весь код приложения работает корректно:

Codeception PHP Testing Framework v2.2.8
Powered by PHPUnit 5.7.9 by Sebastian Bergmann and contributors.

Unit Tests (28) ------------------------------------------------------------------
 ContactFormTest: Send email (1.05s)
 LoginFormTest: Login no user (0.42s)
 LoginFormTest: Login wrong password (0.03s)
...
 UserTest: Save new password (1.01s)
 UserTest: Scenarios | "admin update" (0.03s)
----------------------------------------------------------------------------------

Time: 7.03 seconds, Memory: 24.00MB

OK (28 tests, 84 assertions)

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

Итак, начнём с банального.

Разделение конфигурации

По умолчанию в yii2-app-basic нет разделения файлов конфигурации на общие и локальные. Имеется всего такой набор:

config
├── console.php
├── web.php
├── params.php
├── db.php
├── test.php
└── test_db.php

Это неудобно при использовании систем контроля версий.

В первой части мы переработали файлы по примеру yii2-app-advanced, добавив наследование конфигурации:

config
├── .gitignore
├── common.php
├── common-local.php
├── console.php
├── console-local.php
├── web.php
├── web-local.php
├── params.php
└── params-local.php

чтобы в файле web/index.php склеивать нужный комплект вместе:

$config = yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../config/common.php'),
    require(__DIR__ . '/../config/common-local.php'),
    require(__DIR__ . '/../config/web.php'),
    require(__DIR__ . '/../config/web-local.php')
);

Это избавило нас от необходимости копировать одни и те же секции в console.php и web.php путём переноса всего общего кода в common.php.

Наш файл config/.gitignore:

*-local.php

укажет Git-у игнорировать локальные файлы. В итоге мы можем делиться общими файлами и хранить персональные настройки в локальных.

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

Неразделённой осталась только тестовая конфигурация:

config
├── ...
├── test.php
└── test_db.php

где внутри файла test_db.php вписаны настройки подключения к базе данных:

<?php
<?php
$db = require(__DIR__ . '/db.php');
// test database! Important not to run tests on production or development databases
$db['dsn'] = 'mysql:host=localhost;dbname=yii2_basic_tests';
return $db;

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

Для этого аналогично переделаем имеющуюся структуру:

config
├── ...
├── test.php
└── test_db.php

на новую:

config
├── ...
├── test.php
└── test-local.php

с разделением на общий test.php (где обнулим параметр dsn и добавим только отключения в тестах некоторых компонентов):

return [
    'id' => 'basic-tests',
    'language' => 'en-US',
    'components' => [
        'mailer' => [
            'useFileTransport' => true,
        ],
        'urlManager' => [
            'showScriptName' => true,
        ],
        'db' => [
            'dsn' => '',
        ],
    ],
];

и на локальный файл test-local.php с кодом:

return [
    'components' => [
        'db' => [
            'dsn' => 'mysql:host=localhost;dbname=seokeys_test',
        ],
    ],
];

В итоге получим однообразную структуру:

config
├── .gitignore
├── common.php
├── common-local.php
├── console.php
├── console-local.php
├── web.php
├── web-local.php
├── test.php
├── test-local.php
├── params.php
└── params-local.php

Осталось изменить все файлы, которые пока используют старую конфигурацию.

У нас это общие настройки модуля Yii2 в codeception.yml:

actor: Tester
paths:
    tests: tests
    log: tests/_output
    data: tests/_data
    helpers: tests/_support
settings:
    bootstrap: _bootstrap.php
    memory_limit: 1024M
    colors: true
modules:
    config:
        Yii2:
            configFile: 'config/test.php'
            cleanup: false

Удалим отсюда этот параметр configFile.

Ещё это консольный файл tests/bin/yii:

$config = yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../config/console.php'),
    [
        'components' => [
            'db' => require(__DIR__ . '/../../config/test_db.php')
        ]
    ]
);
$application = new yii\console\Application($config);

Заменяем в нём эту загрузку параметров на новую склейку из нескольких путей:

$config = yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../config/common.php'),
    require(__DIR__ . '/../../config/common-local.php'),
    require(__DIR__ . '/../../config/console.php'),
    require(__DIR__ . '/../../config/console-local.php'),
    require(__DIR__ . '/../../config/test.php'),
    require(__DIR__ . '/../../config/test-local.php')
);
 
$application = new yii\console\Application($config);

Далее для склейки и для удобства дополнительного конфигурирования каждого вида тестов добавим подпапку tests/_config:

tests
├── ...
└── _config
    ├── acceptance.php
    ├── functional.php
    └── unit.php

в acceptance.php и unit.php поместим данный код:

<?php
<?php
return yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../config/common.php'),
    require(__DIR__ . '/../../config/common-local.php'),
    require(__DIR__ . '/../../config/web.php'),
    require(__DIR__ . '/../../config/web-local.php'),
    require(__DIR__ . '/../../config/test.php'),
    require(__DIR__ . '/../../config/test-local.php'),
    [
 
    ]
);

Внимания заслуживает functional.php. В функциональных тестах точкой входа является корневая папка, из которой мы запускаем тесты, а не папка web. Соответственно, псевдоним @webroot автоматически выставится приложением на корневую директорию проекта.

Это чревато тем, что AssetManager в функциональных тестах будет публикавать скрипты не в ту папку, и загруженные файлы будут попадать не в web/uploads. Путь псевдонима @webroot мы не можем выставить напрямую в конфигурации, так как он заполняется на основе $request->getScriptFile():

namespace yii\web;
 
class Application extends \yii\base\Application
{
    ...
 
    protected function bootstrap()
    {
        $request = $this->getRequest();
        Yii::setAlias('@webroot', dirname($request->getScriptFile()));
        Yii::setAlias('@web', $request->getBaseUrl());
 
        parent::bootstrap();
    }
}

Поэтому в tests/_config/functional.php мы можем дополнительно перенастроить параметр scriptFile в request:

<?php
<?php
return yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../config/common.php'),
    require(__DIR__ . '/../../config/common-local.php'),
    require(__DIR__ . '/../../config/web.php'),
    require(__DIR__ . '/../../config/web-local.php'),
    require(__DIR__ . '/../../config/test.php'),
    require(__DIR__ . '/../../config/test-local.php'),
    [
        'components' => [
            'request' => [
                'scriptFile' => dirname(dirname(__DIR__)) . '/web/index-test.php',
            ],
        ],
    ]
);

Теперь перестроим наши тестовые пакеты. Мы уже удалили секцию modules из корневого codeception.yml. Вместо неё индивидуально пропишем configFile в tests/unit.suite.yml:

class_name: UnitTester
modules:
    enabled:
      - Asserts
      - Yii2:
            part: [orm, email]
            configFile: 'tests/_config/unit.php'

Аналогично в tests/functional.suite.yml:

class_name: FunctionalTester
modules:
    enabled:
      - Filesystem
      - Yii2:
            configFile: 'tests/_config/functional.php'

и tests/acceptance.suite.yml.example:

class_name: AcceptanceTester
modules:
    enabled:
        - WebDriver:
            url: http://127.0.0.1:8080/
            browser: firefox
        - Yii2:
            part: orm
            entryScript: index-test.php
            configFile: 'tests/_config/acceptance.php'

После этого остался входной файл приёмочного тестирования web/index-test.php и его заготовка environments/dev/web/index-tests.php с кодом:

require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
 
$config = require(__DIR__ . '/../config/test.php');
 
(new yii\web\Application($config))->run();

Заменим в нём строку с require:

require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
 
$config = require(__DIR__ . '/../tests/_config/acceptance.php');
 
(new yii\web\Application($config))->run();

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

Как мы помним, мы скопировали из yii2-app-advanced скрипт init с папкой environments. Так что можно поместить заготовку нашего файла туда в подпапку окружения dev:

environments
├── index.php
├── dev
│   ├── config
│   │   ├── common-local.php
│   │   ├── console-local.php
│   │   ├── params-local.php
│   │   ├── test-local.php
│   │   └── web-local.php
│   ├── web
│   │   ├── index.php
│   │   └── index-test.php
│   └── yii
└── prod
    ├── config
    │   ├── common-local.php
    │   ├── console-local.php
    │   ├── params-local.php
    │   └── web-local.php
    ├── web
    │   └── index.php
    └── yii

В prod-окружении тесты не запускают, так что туда эти данные помещать не нужно.

В итоге, при запуске команды:

php init

при установке приложения эти заготовки файлов автоматически скопируются на их исходные места.

Проверим правильность установки. Для этого можно создать тестовую базу, прописать её имя в своём config/test-local.php и попробовать запустить миграции для того самого скрипта yii:

php tests/bin/yii migrate

Если настройки базы указаны верно, то миграция создаст в ней такую же таблицу user и свою вспомогательную migration.

Именно так из двух скриптов yii и tests/bin/yii можно автоматически обновлять рабочую и тестовую базы одними и теми же миграциями нашего приложения.

Запуск встроенных тестов

Попробуем запустить команду codecept:

vendor/bin/codecept

Мы должны увидеть приветствие:

Codeception version 2.2.8

Мы можем попробовать запустить тесты по умолчанию из комплектации yii2-app-basic командой:

vendor/bin/codecept run unit

или:

vendor/bin/codecept run functional

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

Установка Selenium

По умолчанию доступны только unit- и functional-тесты. Для запуска приёмочных (acceptance) необходимо установить Selenium Standalone Server, который будет запускать для нас браузер Firefox или Google Chrome.

По умолчанию в стандартном composer.json из yii2-app-basic устанавливается базовая версия codeception/base пакета Codeception:

"require-dev": {
    "yiisoft/yii2-debug": "~2.0.0",
    "yiisoft/yii2-gii": "~2.0.0",
    "yiisoft/yii2-faker": "~2.0.0",

    "codeception/base": "^2.2.3",
    "codeception/verify": "~0.3.1",
    "codeception/specify": "~0.4.3"
},

Она позволяет запускать модульные и функциональные тесты, но не содержит модуля для работы с приёмочными тестами через Selenium.

Заменим базовый пакет на полный запуском этих команд:

composer remove --dev codeception/base
composer require --dev codeception/codeception

или вручную исправим composer.json и запустим composer update.

Второй на очереди – Selenium-сервер. Это .jar-приложение. Для него, соответственно, нужно установить JRE от Java (но если у вас уже установлен редактор PhpStorm, то Java у уже есть).

С новой версии Selenium Server 3.0 драйверы взаимодействия с браузерами оказались вынесен в отдельные бинарники. Для Firefox выше версии 48 потребуется отдельно догрузить GeckoDriver и запускать сервер в командной строке вместе с ним:

java -jar -Dwebdriver.gecko.driver=/path/to/geckodriver /path/to/selenium-server-standalone-3.0.1.jar

После этого можно переименовать tests/acceptance.suite.yml.example в tests/acceptance.suite.yml, в новом окне консоли запустить свой сайт:

php yii serve

и пробовать позапускать приёмочные тесты:

vendor/bin/codecept run acceptance

С ними можно пока потренироваться на свежеустановленной копии yii2-app-basic.

Написание своих тестов

Для заполнения базы тестовыми наборами данных мы можем использовать так называемые фикстуры.

В новой папке tests/_fixtures создадим класс UserFixture с таким кодом:

namespace tests\_fixtures;
 
use yii\test\ActiveFixture;
 
class UserFixture extends ActiveFixture
{
    public $modelClass = 'app\modules\user\models\User';
    public $dataFile = '@tests/_fixtures/data/user.php';
}

и в подпапке tests/_fixtures/data создадим файл user.php с нашими наборами:

return [
    [
        'username' => 'admin',
        'auth_key' => 'eckb2DLY9uv6r1hM6D73eoHPvv6BfnXc',
        'password_hash' => '$2y$13$D8areN6YSJh.fmR.Ww/sWOJ8EXRxNS9c7u7ubIrVozomTR8MY0PbO',
        'password_reset_token' => null,
        'email_confirm_token' => null,
        'created_at' => '1439635619',
        'updated_at' => '1439635619',
        'email' => 'admin@example.com',
        'status' => 1,
    ],
    ...
];

Далее для поддержки фикстур подключим часть fixtures в секции part для модуля Yii2 в unit.suite.yml

class_name: UnitTester
modules:
    enabled:
      - Asserts
      - Yii2:
            part: [orm, fixtures, email]
            configFile: 'tests/_config/unit.php'

и acceptance.suite.yml:

class_name: AcceptanceTester
modules:
    enabled:
        - WebDriver:
            url: http://127.0.0.1:8080/
            browser: firefox
            window_size: 1024x768
        - Yii2:
            part: [orm, fixtures]
            entryScript: index-test.php
            configFile: 'tests/_config/acceptance.php'

Далее откроем tests/_bootstrap.php и в самом низу добавим строку:

Yii::setAlias('@tests', __DIR__);

чтобы фреймворком корректно распознавались пути с псевдонимом @tests и работала автозагрузка классов фикстур из пространства имён tests.

Теперь возьмем уже имеющиеся стандартные тесты, идущие в комплекте yii2-app-basic, переделаем их под свои нужды и допишем свои.

Хорошая практика – раскладывать проверяющие классы по таким же папкам, где лежат оригинальные. Поэтому переместим всё как нам нужно:

project
├── tests
│   ├── _config
│   ├── _data
│   ├── _fixtures
│   │   ├── data
│   │   │   └── user.php
│   │   └── UserFixture.php
│   ├── _output
│   ├── _support
│   │   ├── _generated
│   │   ├── AcceptanceTester.php
│   │   ├── FunctionalTester.php
│   │   └── UnitTester.php
│   ├── bin
│   │   └── yii
│   │
│   ├── acceptance
│   │   ├── _bootstrap.php
│   │   ├── admin
│   │   │   └── HomeCest.php
│   │   ├── _bootstrap.php
│   │   ├── main
│   │   │   ├── ContactCest.php
│   │   │   └── HomeCest.php
│   │   └── user
│   │       ├── profile
│   │       │   └── HomeCest.php
│   │       ├── LoginCest.php
│   │       ├── PasswordResetCest.php
│   │       └── SignupCest.php
│   │
│   ├── functional
│   │   ├── _bootstrap.php
│   │   ├── admin
│   │   │   ├── HomeCest.php
│   │   │   └── UsersCest.php
│   │   ├── main
│   │   │   ├── ContactCest.php
│   │   │   └── HomeCest.php
│   │   └── user
│   │       ├── profile
│   │       │   ├── HomeCest.php
│   │       │   ├── PasswordChangeCest.php
│   │       │   └── ProfileUpdateCest.php
│   │       ├── LoginCest.php
│   │       ├── PasswordResetCest.php
│   │       └── SignupCest.php
│   │
│   ├── unit
│   │   ├── _bootstrap.php
│   │   ├── _fixtures
│   │   │   └── data
│   │   │       ├── user-email-confirm.php
│   │   │       ├── user-password-change.php
│   │   │       └── user-password-reset.php
│   │   └── modules
│   │       ├── admin
│   │       │   └── models
│   │       │       └── UserTest.php
│   │       ├── main
│   │       │   └── forms
│   │       │       └── ContactFormTest.php
│   │       └── user
│   │           ├── forms
│   │           │   ├── EmailConfirmTest.php
│   │           │   ├── ...
│   │           │   └── SignupFormTest.php
│   │           └── models
│   │               └── UserTest.php
│   │
│   ├── _bootstrap.php
│   ├── acceptance.suite.yml
│   ├── functional.suite.yml
│   └── unit.suite.yml
│
codeception.yml
README.md

Код каждого файла можно посмотреть в исходниках на GitHub.

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

$I->amLoggedInAs($I->grabRecord(User::className(), ['username' => $username]));

Объекту $I для удобства мы можем добавлять свои методы. Для этого откроем класс tests/_support/FunctionalTester.php и допишем то, что нам пригодится:

class FunctionalTester extends \Codeception\Actor
{
    use _generated\FunctionalTesterActions;
 
    public function amLoggedInAsAdmin()
    {
        $this->amLoggedInByUsername('admin');
    }
 
    public function amLoggedInAsUser()
    {
        $this->amLoggedInByUsername('user');
    }
 
    public function amLoggedInByUsername($username)
    {
        $I = $this;
        $I->amLoggedInAs($I->grabRecord(User::className(), ['username' => $username]));
    }
}

Теперь мы можем просто вызывать $I->amLoggedInAsAdmin() для быстрого входа в систему.

Аналогично добавляем аналогичные вещи в tests/_support/AcceptanceTester.php:

class AcceptanceTester extends \Codeception\Actor
{
    use _generated\AcceptanceTesterActions;
 
    public function amLoggedInAsAdmin()
    {
        $this->amLoggedInByCredentials('admin', 'adminpass');
    }
 
    public function amLoggedInAsUser()
    {
        $this->amLoggedInByCredentials('user', 'userpass');
    }
 
    public function amLoggedInByCredentials($username, $password)
    {
        $I = $this;
        $I->amOnPage(Url::to(['/user/default/login']));
        $I->seeInTitle('Login');
        $I->fillField('#loginform-username', $username);
        $I->fillField('#loginform-password', $password);
        $I->click('login-button');
        $I->wait(2);
        $I->see('Profile', '.nav');
    }
}

Приёмочные тесты более высокоуровневые и не всегда нужны при наличии функциональных. Приёмочные полезны для проверки JavaScript и CSS. Клиентских скриптов у нас пока нет, так что пока их можно просто продублировать частично из функциональных с добавлением пауз для Selenium:

$I->wait(1);

после нажатия каждой кнопки.

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

После установки, если это наш новый проект, генерируем классы тестеров:

vendor/bin/codecept build

Дальше пробуем запустить сначала модульные и интеграционные из папки unit:

vendor/bin/codecept run unit

Успешный результат выглядит примерно так:

Codeception PHP Testing Framework v2.2.8
Powered by PHPUnit 5.7.9 by Sebastian Bergmann and contributors.

Unit Tests (28) ------------------------------------------------------------------
 ContactFormTest: Send email (1.05s)
 LoginFormTest: Login no user (0.42s)
 LoginFormTest: Login wrong password (0.03s)
...
 UserTest: Save new password (1.01s)
 UserTest: Scenarios | "admin update" (0.03s)
----------------------------------------------------------------------------------

Time: 7.03 seconds, Memory: 24.00MB

OK (28 tests, 84 assertions)

И запустим функциональные:

vendor/bin/codecept run functional

и увидим похожий результат:

Codeception PHP Testing Framework v2.2.8
Powered by PHPUnit 5.7.7 by Sebastian Bergmann and contributors.

Functional Tests (46) ------------------------------------------------------------
 HomeCest: Test access (0.11s)
 HomeCest: Test home page (0.04s)
...
 ProfileUpdateCest: Update with wrong fields (0.06s)
 ProfileUpdateCest: Update success (0.07s)
----------------------------------------------------------------------------------

Time: 7.5 seconds, Memory: 52.00MB

OK (46 tests, 82 assertions)

С виду здесь нет никакой разницы, но Codeception вместо создания объектов и вызова методов будет эмулировать запуск приложения, расставляя $_GET, $_POST и $_SERVER так, как будто мы открываем страницы и отправляем POST-запросы.

Для запуска реальных приёмочных тестов нужно поднять тестовый сайт по адресу http://localhost:8080/index-test.php. Для этого по подсказке инструкции в README.md откроем ещё одну консоль и в ней запустим PHP-сервер:

yii serve

Он нам сообщит о своей готовности:

Server started on http://localhost:8080/
Document root is "/web"
Quit the server with CTRL-C or COMMAND-C.

Откроем ещё одно окно консоли и запустим Selenium:

java -jar -Dwebdriver.gecko.driver=/path/to/geckodriver /path/to/selenium-server-standalone-3.0.1.jar

Увидим его приветствие:

12:58:15.076 INFO - Selenium build info: version: '3.0.1', revision: '1969d75'
12:58:15.077 INFO - Launching a standalone Selenium Server

И, запустив в первоначальной консоли:

vendor/bin/codecept run acceptance

мы должны увидеть на экране запущенный браузер, в котором будут сами открываться страницы, заполняться поля форм и нажиматься кнопки. При этом в консоли будет выводиться такой же как у функциональных результат:

Codeception PHP Testing Framework v2.2.8
Powered by PHPUnit 5.7.7 by Sebastian Bergmann and contributors.

Acceptance Tests (11) -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 HomeCest: Ensure that home page works (0.47s)
 HomeCest: Test access (0.28s)
...
 PasswordResetCest: Request successfully (2.64s)
 SignupCest: Signup successfully (3.89s)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Time: 25.78 seconds, Memory: 18.00MB

OK (11 tests, 21 assertions)

Если какой-либо тест завершится с ошибкой, то можно будет посмотреть дамп и скриншот ошибочной страницы в папке tests/_output.

Анализ покрытия кода тестами

Этот анализ позволяет посмотеть, какие участки кода отработали в ходе тестирования. То есть оценить, весь ли код протестирован. Это производится за счёт сбора статистики запуска кода отладчиком XDebug.

В Ubuntu и Debian устанавливаем его стандартно из :

sudo apt-get install php5-xdebug

В Windows нужно скачать php_xdebug.dll и подключить его в php.ini:

[xdebug]
zend_extension_ts=C:/php/ext/php_xdebug.dll

Но если в ваших тестах используется $this->specify(...), то будет постоянно вываливаться ошибка из-за ограничений уровня вложенности. Для решения проблемы нужно открыть php.ini или /etc/php/conf.d/xdebug.ini и дописать:

xdebug.max_nesting_level = 1000

В наших тестах, например, эта вешь не испольуется.

Далее в общем файле codeception.yml раскомментируем опции анализатора покрытия (test coverage) нашего кода. Включаем только папки с кодом и исключаем всё лишнее. Другие секции нас вполне устраивают, поэтому всё остальное оставляем как есть:

actor: Tester
paths:
    tests: tests
    log: tests/_output
    data: tests/_data
    helpers: tests/_support
settings:
    bootstrap: _bootstrap.php
    memory_limit: 1024M
    colors: true
modules:
    config:
        Yii2:
            cleanup: false

coverage:
    enabled: true
    whitelist:
        include:
            - components/*
            - mail/*
            - modules/*
            - views/*
        exclude:
            - modules/admin/messages/*
            - modules/main/messages/*
            - modules/user/messages/*

На этом общее конфигурирование завершено.

Попробуем запустить всё снова, но с анализом покрытия:

vendor/bin/codecept run unit,functional --coverage-html

И после завершения посмотрим _output/coverage/index.html и увидим примерно следующее:

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

С тестами пока всё. Далее мы перекомпонуем наши модули для их большей самостоятельности.

Следующая часть: Организация переносимых модулей

Комментарии

 

bobpps

Большущее спасибо! Вы, как всегда, на высоте!

Ответить

 

Олег Мусатов

Неделю, как взялся за чтение Вашего блога. Понял в yii2 больше, чем за месяц до этого. Очень качественная и подробная информация.

Жду не дождусь статьи по подключению rbac.

Ответить

 

Алексей

И еще, что бы работал coverage, в php.ini должен быть включен php_xdebug.dll, иначе будет ругаться на отсутствие драйвера - No code coverage driver available

Ответить

 

Дмитрий Елисеев

Спасибо! Добавил в статью.

Ответить

 

Grey – webschool.pspu.ru

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

Ответить

 

Дмитрий Елисеев

Есть пример на эту тему в самом расширении.

Ответить

 

Grey – webschool.pspu.ru

Спасибо

Ответить

 

Кабаченко Виктор

Большое спасибо за вашу титаническую работу. Таких учебных материалов по тестированию php-проектов еще не было. Хочется попросить вас не оставлять эту тему и при развитии этого проекта обратить внимание на технологию тестирования javascript/ajax с помощью приемочных тестов, ну а также побольше внимания уделить mocks/stubs в модульном тестировании

Ответить

 

nikosid

Подскажите в чём беда. Я сделал всё по инструкции, но у меня ломаются тесты acceptance.
После долгих мучений, я скачал и установил себе голый yii2-app-advanced и с ним та же беда, не отрабатывают тесты для LoginPage например, а именно те, которые должны увидеть ошибку:

 Step  I see "Username cannot be blank.",".help-block"
 Fail  Element located either by name, CSS or XPath element with '.help-block' was not found.


и в _output в html и скриншоте вижу, что ошибка не выводилась.
При этом просто в браузере всё отрабатывает.

Ответить

 

nikosid

Забыл сказать, это только в случае с WebDriver.
Если запускать с PhpBrowser, то всё ок.

Ответить

 

Дмитрий Елисеев

Возможно не успевают появиться. Можно попробовать паузы в sleep(...) увеличить.

Ответить

 

Роман Пулиян

Привет, а как сделать, чтобы перед запуском теста база полностью очищалась от данных из предыдущих тестов? Само как-то должно произойти, или я руками должен очистку делать, например в setUp()?
setUp() и tearDown() срабатывают перед и после каждого теста, верно?

Ответить

 

Дмитрий Елисеев

Я вручную вычищаю. Либо в setUp(), либо в конце теста. А вообще стараюсь делать так, чтобы тесты друг другу не мешали.

Ответить

 

nikosid

А что за файл генерируется при каждом тестировании?

tests/codeception/common/_support/_generated/UnitTesterActions.php

Содерживое его не меняется, а только [STAMP]
В общем-то вот такое содержимое

<?php  //[STAMP] 3855f4aae2d90a3240564b5fb541a01d
namespace tests\codeception\common\_generated;

trait UnitTesterActions
{
    /**
     * @return \Codeception\Scenario
     */
    abstract protected function getScenario();   
}
Ответить

 

Дмитрий Елисеев

Раньше в 2.0 для подключения модулей перегенерировался целиком весь AcceptanceTester. Это не позволяло добавлять туда свои методы вроде $I->login('name', 'password'), так как при перегенерации все наши методы перезатирались.

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

class AcceptanceTester extends \Codeception\Actor
{
    use _generated\AcceptanceTesterActions;

    public function login($name, $password)
    {
        $I = $this;
        $I->amOnPage('/login');
        $I->submitForm('#loginForm', [
            'login' => $name, 
            'password' => $password
        ]);
        $I->see($name, '.navbar');
    } 
}

Пример из http://codeception.com/docs/06-ReusingTestCode.

Ответить

 

nikosid

Как с ним правильно поступить? Заигнорить в гите?

Ответить

 

Дмитрий Елисеев

Можно и заигнорить.

Ответить

 

Sergey

Дмитрий, такой вопрос по тестированию.
Исходные данные:
есть RBAC на основе DB manager. есть пользователи с разными ролями(у ролей свои разрешения и т.д.).

Вопросы:
как можно тестировать настройки доступа по RBAC, если пользователям нужно выставить права/роли при регистрации/добавлении?
т.е. к примеру хочу использовать фикстуры, но тогда как мне одновременно с определением пользователей задать привязки ролей (через $this->users[0] - можно ведь получить только данные фикстуры, но не ID вставленной записи - или ошибаюсь?)?
или если я задам в основной БД все роли и заранее создам тестовых пользователей, то смогу ли использовать фикстуры (не перепишется ли эта информация)? имею ввиду фикстуры как для таблицу пользователей, так и для других таблиц?
как я понимаю каждая фикстура отвечает за свою таблицу, верно?

заранее спасибо!

Ответить

 

Дмитрий Елисеев

> если я задам в основной БД все роли и заранее создам тестовых пользователей, то смогу ли использовать фикстуры (не перепишется ли эта информация)

Именно этих тестовых пользователей с ролями и создавайте в фикстурах. Они для этого и предназначены. Тестирование производится в тестовой БД, а не в основной. Все данные из фикстур пойдут туда.

> как я понимаю каждая фикстура отвечает за свою таблицу, верно?

Да. И к тесту регистрации подключайте все нужные для него UserFixture, AuthItemFixture, AuthAssignmentFixture и т. п.

> можно ведь получить только данные фикстуры, но не ID вставленной записи - или ошибаюсь?

Для заранее создаваемых в фикстурах пропишите id:

[
    'id' => 1,
    'username' => 'admin',
    'email' => 'admin@example.com',
],

и получайте через $this->users[0]['id'].

А вновь созданных после регистрации (которых нет в $this->users) можно просто найти в базе по имени, под которым их регистрировали:

$user = User::findOne('name' => 'new_name');

и у них брать $user->id;

Ответить

 

Анатолий Белов

Все супер, труд титанический. Жаль, что не работает. Вроде всё по инструкции, ан нет.
Для меня проблема в том, что я не могу отличить обзорный код от рабочего. Сперва пишут так, далее вы говорите, что теперь нужно так, переделываю, потом еще, потом еще, потом ничего не работает и очень сложно понять что. Возможно, лучше отделить то, что в итоге не будет внесено в проект спойлером. Сейчас нереально проследить нить изменений.
С первой статьи проекта, рабочего кода нет, лишь концепт. В голове каша. У меня другие версии компонентов и php, может по этому.
Смотрел около семи часов скринкаст по тестированию, теперь применяю миграции для тестов и тупик полный, ничего за эти ошибки нет в сети.

Ответить

 

Дмитрий Елисеев

Просто год назад я не знал, что и как буду переделывать сегодня.

Ответить

 

Анатолий Белов

Согласен, что теперь сделаешь... как есть. Я думал сперва, вы специально так сделали. Чтобы мы мозг включали. Но местами слишком запутано получается. Спасибо, что делитесь своим опытом разработки, это главное. Тяжело найти реальный опыт, к тому же, вы показываете множество вариантов подхода. Уже почти досмотрел, что у вас есть, буду ждать новых вебинаров и статей. Удачи.

Ответить

 

Александр

Круто, спасибо за статью! Только начала по ней настраивать свое приложение и тут же вопрос возник. Дело в том, что в моем приложении есть 2 модуля (user, rbac), остальное пока в бекенде (categories, posts). Так вот миграции по модулю user лежат в модуле: modules/user/mogrations, остальные миграции по постам и категориям как обычно в console/migrations. При запуске php tests/codeception/bin/yii migrate конечно пытается создаться таблицы только post && category, хотя сначала должна быть таблица user (на нее ссылаются таблицы приложения), но о ней (о миграции создания таблицы user) тесты ничего не знают.
Дмитрий, как можно указать тестам очередность директорий миграций, с которых должна быть сборка?

Ответить

 

Дмитрий Елисеев

Подключите любое расширение вроде multipath-migrations и пропишите ему все пути с миграциями.

Ответить

 

Александр

О, спасибо, буду пробовать

Ответить

 

Андрей Русскин

Подскажите пожалуйста по UNIT тестированию.
Не могу настроить автозагрузку классов
Есть например модель User c с методом

public function fake(){
    return true;
}

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

__DIR__.'/../../models/User.php';

как автоматически их подключать?

и как запустить консольное приложения для тестирования экшенов консольного контроллера?

И не могу обратиться к БД
получаю ошибку TaskTest: User exception

PHP Fatal error:  Call to a member function getDb()

Что я делаю не так? :(

Ответить

 

Дмитрий Елисеев

В стандартных приложениях автозагрузка работает автоматически, если наследовать тесты от yii\codeception\TestCase.

А консольные контроллеры не тестировал.

Ответить

 

Андрей Русскин

да в том то и дело что наследуюсь от \yii\codeception\TestCase
и пытаюсь прогнать тест

public function testMe()
{
    $model = \app\models\User::find()->all();
    $this->assertEquals(3,count($model));
}

и получаю ошибку
MePHP Fatal error: Class 'app\models\User' not found in /var/www/test1/tests/unit/CronControllerTest.php

/var/www/test1/tests/_bootstrap.php содержит:

<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');

defined('YII_TEST_ENTRY_URL') or define('YII_TEST_ENTRY_URL', parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
defined('YII_TEST_ENTRY_FILE') or define('YII_TEST_ENTRY_FILE', dirname(dirname(__DIR__)) . '/web/index-test.php');

require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

$_SERVER['SCRIPT_FILENAME'] = YII_TEST_ENTRY_FILE;
$_SERVER['SCRIPT_NAME'] = YII_TEST_ENTRY_URL;
$_SERVER['SERVER_NAME'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_HOST);
$_SERVER['SERVER_PORT'] =  parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PORT) ?: '80';

Yii::setAlias('@tests', dirname(__DIR__));
Yii::setAlias('@app', dirname(dirname(__DIR__)));

чтото уже запутался куда рыть

Ответить

 

Дмитрий Елисеев
Yii::setAlias('@tests', __DIR__);
Yii::setAlias('@app', dirname(__DIR__));
Ответить

 

Андрей Русскин

Спасибо :)
никогда не пользовался dirname() потому и лопухнулся :(

Ответить

 

Katrin Parfenova

Пишу юнит тест...

public function testProfileWrongData()
    {
        $model = new Profile([
            'lang_id' => -2,       // д.б integer
            'user_id' => -99,        //   д.б integer и ищет такого юзера в базе
            'name' => 2,              // д.б срока
        ]);
        expect('model is not valid', $model->validate())->false();
        expect('lang_id is incorrect', $model->errors)->hasKey('lang_id');
        expect('user_id is incorrect', $model->errors)->hasKey('user_id');
        expect('name_phrase is incorrect', $model->errors)->hasKey('name');
    } 

правила проверки

  public function rules()
    {
        return [
            [['lang_id', 'user_id', 'name'], 'required'],
            [['lang_id', 'user_id'], 'integer'],
            [['name'], 'string', 'max' => 50],
            [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
        ];
    }

так вот в error на lang_id = -2 в ошибки не падает...все типа хорошо, если ставлю там строку 'test' - то ошибка выдается, что д.б integer....почему не проверяет на отрицательность..где я туплю...

Ответить

 

Дмитрий Елисеев

Добавьте 'exist' валидатор для 'lang_id', если это связь.

Ответить

 

Олег Кузьменко

Ошибка, потому что integer вполне может быть отрицательным числом, с точки зрения типа данных - это правильно и ошибки в валидации нет.

Укажите параметр

'min' => 1

там, где написан тип данных (аналогично полю 'name' ниже).

Ответить

 

Роман

Пытаюсь провести миграцию тестовой базы

php tests/codeception/bin/yii migrate

В консоли валятся ошибки:

PHP Fatal error:  Uncaught exception 'yii\base\UnknownPropertyException' with message 'Setting unknown property: yii\console\ErrorHandler::errorAction' in Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\base\Component.php:197
Stack trace:
#0 Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\BaseYii.php(521): yii\base\Component->__set('errorAction', 'main/default/er...')
#1 Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\base\Object.php(105): yii\BaseYii::configure(Object(yii\console\ErrorHandler), Array)
#2 [internal function]: yii\base\Object->__construct(Array)
#3 Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\di\Container.php(374): ReflectionClass->newInstanceArgs(Array)
#4 Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\di\Container.php(153): yii\di\Container->build('yii\\console\\Err...', Array, Array)
#5 Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\BaseYii.php(344): yii\di\Container->get('yii\\console\\Err...', Array, Array)
#6 Z:\Programs\Sites\yi in Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\base\Component.php on line 197

На просторах нэта нарыл информацию, мол нужно вставить блок:

'components' => [
            'error' => [
                'errorAction' => 'main/default/error',
        ],

в config/console.php.

Вставлял - не работает.

Почему? Или вставляю не туда? Или вообще всё неправильно?

Ответить

 

Дмитрий Елисеев

Компонент errorHandler с errorAction должен быть только в config/web.php. В консоли и в common он не нужен.

Ответить

 

Роман

Переместил созданный config-local.php в envoronments/dev/tests/codeception/

После этого, выполнил

php tests/codeception/bin/yii migrate


В итоге в site/config появилась поддиректоря tests/codeception/config-local.php с файлом.

????
Так должно быть для паблик проектов?

Но, самая главная проблема - это то, что не работает мигация в тестовую БД.

Уже всё 10 раз пересмотрел.

Z:\Programs\Sites\yii2-basic-elisdn\www>php tests/codeception/bin/yii migrate
PHP Fatal error:  Uncaught exception 'yii\base\UnknownPropertyException' with message 'Setting unknown property: yii\console\ErrorHandler::errorAction' in Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\base\Component.php:197
Stack trace:
#0 Z:\Programs\Sites\yii2-basic-elisdn\www\vendor\yiisoft\yii2\BaseYii.php(521): yii\base\Component->__set('errorAction', 'main/default/er...')

Вот, что я делаю не так?
Почему обработчик ругается на errorHandler ?

Ответить

 

Дмитрий Елисеев

> Переместил созданный config-local.php в envoronments/dev/tests/codeception/

Зачем?

> Но, самая главная проблема - это то, что не работает мигация в тестовую БД.

Настройки компонента errorHandler должны быть только в config/web.php.

Ответить

 

Роман

Пропустил 1 подкаталог.
Переместил config-local.php, созданный в site/tests/codeception/config в директорию environments/dev/config/tests/codeception.
Как указано Вами Дмитрий.
После этого выполнил init.

Настройки компонента errorHandler только в config/web.php. В блоке components.

Вот и непонимаю почему валятся эксепшены?
Что не так?

Ответить

 

Роман

Вообщем проблема с хандлерами возникла из-за того, что (опять же по инструкции выше) дополнил файл bin/yii с путями как для тестовых конфигов:

return yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../../config/common.php'),
    require(__DIR__ . '/../../../config/common-local.php'),
    require(__DIR__ . '/../../../config/web.php'),
    require(__DIR__ . '/../../../config/web-local.php'),
    require(__DIR__ . '/config.php'),
    require(__DIR__ . '/config-local.php'),
    [
 
    ]
);

А нужно было так:

$config = yii\helpers\ArrayHelper::merge(
    require(YII_APP_BASE_PATH . '/config/common.php'),
    require(YII_APP_BASE_PATH . '/config/common-local.php'),
    require(YII_APP_BASE_PATH . '/config/console.php'),
    require(YII_APP_BASE_PATH . '/config/console-local.php'),
    require(__DIR__ . '/../config/config.php'),
    require(__DIR__ . '/../config/config-local.php')
);

И шторм ни разу не выругался....

Ответить

 

Роман

При попытке установить Composer выдаёт:

Your requirements could not be resolved to an installable set of packages.
...
Installation failed, reverting ./composer.json to its original content.

Так понимаю главный composer.json что лежит в C:\Users\SomeUser\AppData\Roaming\Composer\ у меня кривой?

Где брать оригинал?

Или я неверно рассуждаю?

Ответить

 

Дмитрий Елисеев

В ... как раз данные об ошибке. Если там про bower-asset/jquery, то забыли установить asset-plugin первой строчкой.

Ответить

 

Роман

Сейчас нет возможности просмотреть. Может быть ошибка связана с тем, что у меня уже был установлен Codeception 2.2.1 глобально?

Ответить

 

Роман

Вобщем так и есть, ошибки возникают из-за наличия установленной версии 2.1.*.

Удалил. Установил указанную.

Почему Шторм ругается на строку:

use Codeception\Module;

в FixtureHelper ?

Нэймспэйс Codeception найти не может. Да и я тоже.

Ответить

 

Дмитрий Елисеев

В PhpStorm зайти в File - Settings - Languages & Frameworks - PHP.

Там в Include path добавить папку C:\Users\SomeUser\AppData\Roaming\Composer\vendor

Ответить

 

Роман

Добрый вечер.

При попытке запустить:

codecept build

выскакивает ошибка:

                                             
  [Codeception\Exception\Configuration]       
  Configuration file could not be found.      
  Run `bootstrap` to initialize Codeception. 

На всякий случай выполнил команду
tests\codeception\bin>codecept bootstrap
Не помогает.

В чём может быть дело?

Ответить

 

Дмитрий Елисеев

Запускайте в папке tests, а не tests/codeception/bin.

Ответить

 

Александр

Подскажите пожалуйста, что делать с FOREIGN_KEY_CHECKS. Глобально в субд конечно работает соблюдение ссылочной целостности. Но я не понимаю, делал по примеру, таблица вроде у нас одна только, user, и в ней нет внешних ключей.

Если запускать функциональные тесты с анализом покрытия кода

codecept run functional --coverage-html

то после того как тесты прошли, появляется ошибка (без анализатора всё нормально)

  [yii\db\Exception]
  PDOStatement::execute(): MySQL server has gone away
  The SQL being executed was: SET FOREIGN_KEY_CHECKS = 0

  [yii\base\ErrorException]
  PDOStatement::execute(): MySQL server has gone away

и еще после того как проходят acceptance тесты, не могу посмотреть фэйлы и ошибки, тоже выскакивает

[yii\db\Exception]
  SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
  The SQL being executed was: SET FOREIGN_KEY_CHECKS = 0

  [PDOException]
  SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Ответить

 

Дмитрий Елисеев

MySQL server has gone away - значит MySQL отключился по таймауту.

Ответить

 

Роман

Добрый вечер.
Дмитрий, почему не могу обнаружить после завершения

codecept run unit,functional --coverage-html

файл _output/coverage/index.html

В _output даже папки coverage нет.

Где-то прописать нужно? Где?

Ответить

 

Дмитрий Елисеев

А на свежем yii2-app-basic появляется?

Ответить

 

Роман

Дмитрий, добрый день.
Прошу прощения за продолжение оборвавшегося диалога, небыло доступа к ПК.

Да, на свежем yii2-app-basic появляется.
Где я мог ошибиться?

Ответить

 

Дмитрий Елисеев

А в codeception.yml секцию coverage настроили?

Ответить

 

Роман

Да всё настроено.
Вообщем пропустил этот момент временно. Перешёл к другой главе. Некоторое время спустя. Попробовал протестить и всё появилось. Видимо с Гита скопировал часть кода, относящуюся к следующей главе.

P.S. давно Вас не было слышно...

Ответить

 

Юрий

Здравствуйте!

Подскажите, почему не проходит часть тестов. Запускаю так codecept run unit.

Вываливаются ошибки вида:

tests\codeception\unit\models\ContactFormTest::testContact | email should be send | examples index 0
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in /home/username/.composer/vendor/phpunit/phpunit/src/Framework/TestCase.php on line 851
tests\codeception\unit\models\LoginFormTest::testLoginNoUser
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in /home/username/.composer/vendor/phpunit/phpunit/src/Framework/TestCase.php on line 851

Результат

FAILURES!
Tests: 32, Assertions: 47, Errors: 13, Failures: 2.
Ответить

 

Дмитрий Елисеев

Уберите опцию --no-colors отовсюду.

Ответить

 

Юрий

Скажите, пожалуйста, подробнее где эта опция задается? В ваших статьях ее не нашел.

Ответить

 

Дмитрий Елисеев

Если в PhpStorm по видео настраивали, то там. А если этого нет, то значит в другом дело. Видимо, что PHPUnit обновился сильно.

Ответить

 

Юрий

Нет, PhpStorm не настраивал по видео. Делал, все, как было в ваших постах SeoKeys.

Версии PHPUnit и Codeseption:

Codeception PHP Testing Framework v2.0.16
Powered by PHPUnit 4.7.7 by Sebastian Bergmann and contributors.

У меня, на этой машине стоит PHP 7, я думаю из-за этого возникает проблема. Пробовал, запускать тесты на проекте с гитхаба, были такие же проблемы.

Ответить

 

Дмитрий Елисеев

Может быть. А стандартные со стабильного yii2-app-basic запускаются?

Ответить

 

Юрий

Да, со стандартными, которые идут в yii2 basic, все ок.

Time: 871 ms, Memory: 10.00MB
OK (4 tests, 15 assertions)

Ответить

 

Михаил Петров

Запустил тесты, все ОК. А когда свой начал писать, застрял. Дело в том, что в форма появляется с помощью ajax, это я победил с помощью selenium и wait. Но еще в ней несколько селектов, при изменении первого происходит запрос на сервер и заполняется второй, ну и так по цепочке. Так вот в первом я выбрал вариант с помощью $I->selectOption('theme', 1); Потом дал время на подгрузку для второго:

if (method_exists($I, 'wait')) {
    $I->wait(3); // only for selenium
}


Но все равно не могу из второго ничего выбрать. Я так понимаю, для selenium-а то, что мы в первом селекте что-то выбрали, на является поводом запускать событие change? Как мне его симулировать с помощью codeception, не подскажете? Я не нашел. Спасибо!

Ответить

 

Михаил Петров

Сразу уточняю, executeJS вызывает ошибку
RuntimeException: Call to undefined method AcceptanceTester::executeJS

Ответить

 

Дмитрий Елисеев

Обновил статью на новую структуру папки tests с Yii 2.0.10.

Ответить

 

Spirit Absolute

Спасибо!

Ответить

 

Денис Бондарь

Дмитрий, сообщество, добрый день!
Есть вопрос касательно модульного тестирования ActiveRecord, в котором имеется поле с проверкой на уникальность.
Имеется тестовый метод, который использует провайдер данных и таким образом проверяется отработка валидаторов, в том числе на уникальность. Способ в общем то очень похож на тот, который у Вас в этом видео. Но вот в чем проблема: в таблице до начала теста уже могут быть какие-то данные, что в некоторых случаях делает тест провальным. То есть нарушается повторяемость тестов.
Как можно побороть данную проблему? Можно ли как-то очищать таблицу перед выполнением тестового метода?
Изначально расчет был на фикстуры. Предполагалось, что после окончания теста фикстуры удаляются из таблицы БД, но это не так - таблица очищается непосредственно перед применением фикстур.
Поэтому вопрос: как очистить таблицу перед выполнением тестов, чтобы обеспечить повторяемость? Есть ли для этого в codeception какие либо стандартные средства?

Ответить

 

Дмитрий Елисеев

Сделайте файл данных с пустым return []; и укажите его как dataFile в haveFixtures к этому тесту.

Ответить

 

Денис Бондарь

Спасибо! Как же это все таки было очевидно. И почему я не додумался. :)

Ответить

 

Сергей

Добрый день!
Ставил все по инструкции https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md,
Там же есть один из примеров - запуск тестов из папки common:
vendor/bin/codecept run -- -c common
А как запустить определенный класс/метод на тест, а не все тесты из папки?

Заранее большое спасибо!

Ответить

 

Дмитрий Елисеев
vendor/bin/codecept run unit models -- -c common
vendor/bin/codecept run unit models/UserTest -- -c common
vendor/bin/codecept run unit models/UserTest:testFindUserById -- -c common
Ответить

 

Сергей

Дмитрий, спасибо огромное!

Ответить

 

Костя

А в функциональных тестах Cest можно использовать аннотацию @dataProvider?
Надо ли от чего-нибудь наследовать?
Если нет как можно запустить один тест с разными параметрами?

Ответить

 

Сергей

Пример:

/**
 * @dataprovider pageProvider
 */
public function my(AcceptanceTester $I, \Codeception\Example $example){
    $a = $example[0];
    $b = $example[1];

    expect('а больше б', $a > $b)->true();
}


protected function pageProvider()
{
    return [
        [122, 32],
        [23, 442],
        [23, 8]
    ];
}

Ответить

 

Сергей

вернее указать первым аргументом FunctionalTester $I для функциональных тестов. Сам пример, конечно, просто для ориентира)

Ответить

 

Михаил

Дмитрий, большое спасибо за труд, столько полезных материалов - это здорово!

Ответить

 

Александр

Здравствуйте, может у кого тоже была такая проблема :

Добавил в папку Silenium и geckodriver, пишу команду:

java -jar -Dwebdriver.gecko.driver=/frontend/tests/geckodriver.exe frontend/tests/selenium-server-standalone-3.14.0.jar


Начинается запуск:

00:20:30.402 INFO [GridLauncherV3.launch] - Selenium build info: version: '3.14.0', revision: 'aacccce0'
00:20:30.403 INFO [GridLauncherV3$1.launch] - Launching a standalone Selenium Server on port 4444
2018-10-13 00:20:30.463:INFO::main: Logging initialized @259ms to org.seleniumhq.jetty9.util.log.StdErrLog
00:20:30.687 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444

И на этом моменте запуск бесконечно зависает.
Как можно это поправить? Или хотя бы понять в чем проблема?

Ответить

 

Александр

Попробовал использовать версию 3.0.1
выдало другой лог перед зависанием

01:12:12.064 INFO - Selenium build info: version: '3.0.1', revision: '1969d75'
01:12:12.064 INFO - Launching a standalone Selenium Server
2018-10-13 01:12:12.078:INFO::main: Logging initialized @164ms
01:12:12.119 INFO - Driver class not found: com.opera.core.systems.OperaDriver
01:12:12.119 INFO - Driver provider com.opera.core.systems.OperaDriver registration is skipped:
Unable to create new instances on this machine.
01:12:12.119 INFO - Driver class not found: com.opera.core.systems.OperaDriver
01:12:12.120 INFO - Driver provider com.opera.core.systems.OperaDriver is not registered
01:12:12.125 INFO - Driver provider org.openqa.selenium.safari.SafariDriver registration is skipped:
 registration capabilities Capabilities [{browserName=safari, version=, platform=MAC}] does not match the current platform WIN10
2018-10-13 01:12:12.156:INFO:osjs.Server:main: jetty-9.2.15.v20160210
2018-10-13 01:12:12.171:INFO:osjsh.ContextHandler:main: Started o.s.j.s.ServletContextHandler@f5e5e3{/,null,AVAILABLE}
2018-10-13 01:12:12.271:INFO:osjs.ServerConnector:main: Started ServerConnector@168c294{HTTP/1.1}{0.0.0.0:4444}
2018-10-13 01:12:12.271:INFO:osjs.Server:main: Started @358ms
01:12:12.271 INFO - Selenium Server is up and running

Ответить

 

Александр

Разобрался.
Весьма не очевидный для новичка момент:
Запускается строка

java -jar -Dwebdriver.gecko.driver=/frontend/tests/geckodriver.exe frontend/tests/selenium-server-standalone-3.0.1.jar


Дальше нужно открыть новое окно консоли и там уже запустить yii, и снова открыть новое окно и там уже запускать тесты.

Ответить

 

slo_nik

Доброй ночи.
Пытаюсь настроить codeception так же как phpunit, в phpstorm. В настройках Languages & Frameworks -> PHP -> Test Frameworks
При запуске тестов получаю предупреждение

Testing started at 1:11 ...
/usr/bin/php /tmp/ide-codeception.php run --report -o "reporters: report: PhpStorm_Codeception_ReportPrinter" --no-ansi --no-interaction -c /home/slonik/localhost/www/test.loc/yii2_test/codeception.yml
PHP Warning:  Declaration of PhpStorm_Codeception_ReportPrinter::writeProgress($progress): void should be compatible with PHPUnit\TextUI\ResultPrinter::writeProgress(string $progress): void in /tmp/ide-codeception_24_70.php on line 2
PHP Stack trace:
PHP   1. {main}() /tmp/ide-codeception.php:0
PHP   2. require_once() /tmp/ide-codeception.php:32
Codeception PHP Testing Framework v2.5.1
Powered by PHPUnit 7.3.5 by Sebastian Bergmann and contributors.


Как это можно исправить?

Ответить

 

Гегам – www.gogilink.ru

Здравствуйте. Как я могу найти документацию где будет все методы, которые используется в тестах. Один пример $I->submitForm().

Ответить

 

Дмитрий Елисеев

На сайте Codeception.

Ответить

 

Kevin

Добрый день!
Помогите устранить ошибку, не могу запустить тесты

PHP Deprecated:  Calling the "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead. in 
...\vendor\symfony\event-dispatcher\EventDispatcher.php on line 58

Спасибо!

Ответить

 

Дмитрий Елисеев

Обновите вендоры. Может быть поможет.

Ответить

 

Сергей

Это не помогает

Ответить

 

Дмитрий Елисеев

Значит что-то уже сильно устарело.

Ответить

 

Сергей

Используйте php7.2+

Ответить

 

Roman

Нигде не могу найти информацию - как залить дамп базы перед запуском тестов, чтобы при этом использовать данные из общих настроек. То есть - у codeception есть модуль Db, который умеет заливать дамп. Но он требует, чтобы подключение к базе данных ему указывали отдельно прям для него, в файле codeception.yml - писали там dns, username, password. И я никак не могу найти информацию, как ему скормить те данные, которые уже есть в системе. Чтобы не указывать их второй раз в этом файле. Потому что у меня должно всё запускаться в CI/CD, и на проекте сидит несколько разработчиков, у каждого свои настройки. А тут получается, что надо жёстко задать одни настройки для всех.
Может быть Вы подскажите, как мне залить нужные данные в базу?

Ответить

 

Дмитрий Елисеев

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

Если же просто модуль Db, то можно подставлять переменные окружения из вспомогательного файла params.php или из .env локально и из секретов в CI пайплайне.

А вообще можно внедрить Docker, чтобы у всех разработчиков были одинаковые фиксированные настройки.

Ответить

 

Юрий

Дмитрий, подскажите, пожалуйста, как в файле ./vendor/bin/codecept предустановленная константа имеет значение ./vendor/codeception/codeception, ведь она должна указывать на вышеуказанную папку с bin

Ответить

 

Дмитрий Елисеев

Про какую константу идёт речь?

Ответить

 

Юрий

Про константу __DIR__
Но я уже разобрался. В папке ./vendor/bin/ лежат символические ссылки и в константу __DIR__ падает не путь ./vendor/bin/, а тот, на который указывает символическая ссылка.
Спасибо

Ответить

Оставить комментарий

Войти | Завести аккаунт | Войти через


(никто не увидит)





Можно использовать теги <p> <ul> <li> <b> <i> <a> <pre>