Сервис на 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
$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
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
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
│   │           │   ├── EmailConfirmFormTest.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

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

Ответить

 

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

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

Ответить

 

Grey

Спасибо

Ответить

 

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

Большое спасибо за вашу титаническую работу. Таких учебных материалов по тестированию 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 для функциональных тестов. Сам пример, конечно, просто для ориентира)

Ответить

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

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


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



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