Сервис на 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 │ │ │ ├── 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 например, а именно те, которые должны увидеть ошибку:
и в _output в html и скриншоте вижу, что ошибка не выводилась.
При этом просто в браузере всё отрабатывает.
nikosidЗабыл сказать, это только в случае с WebDriver.
Если запускать с PhpBrowser, то всё ок.
Дмитрий ЕлисеевВозможно не успевают появиться. Можно попробовать паузы в sleep(...) увеличить.
Роман ПулиянПривет, а как сделать, чтобы перед запуском теста база полностью очищалась от данных из предыдущих тестов? Само как-то должно произойти, или я руками должен очистку делать, например в setUp()?
setUp() и tearDown() срабатывают перед и после каждого теста, верно?
Дмитрий ЕлисеевЯ вручную вычищаю. Либо в setUp(), либо в конце теста. А вообще стараюсь делать так, чтобы тесты друг другу не мешали.
nikosidА что за файл генерируется при каждом тестировании?
Содерживое его не меняется, а только [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; }для того чтобы протестировать этот метод надо руками инклюдить файл
как автоматически их подключать?
и как запустить консольное приложения для тестирования экшенов консольного контроллера?
И не могу обратиться к БД
получаю ошибку TaskTest: User exception
Что я делаю не так? :(
Дмитрий ЕлисеевВ стандартных приложениях автозагрузка работает автоматически, если наследовать тесты от 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 вполне может быть отрицательным числом, с точки зрения типа данных - это правильно и ошибки в валидации нет.
Укажите параметр
там, где написан тип данных (аналогично полю 'name' ниже).
РоманПытаюсь провести миграцию тестовой базы
В консоли валятся ошибки:
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/
После этого, выполнил
В итоге в 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 выдаёт:
Так понимаю главный 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
РоманДобрый вечер.
При попытке запустить:
выскакивает ошибка:
На всякий случай выполнил команду
tests\codeception\bin>codecept bootstrap
Не помогает.
В чём может быть дело?
Дмитрий ЕлисеевЗапускайте в папке tests, а не tests/codeception/bin.
АлександрПодскажите пожалуйста, что делать с FOREIGN_KEY_CHECKS. Глобально в субд конечно работает соблюдение ссылочной целостности. Но я не понимаю, делал по примеру, таблица вроде у нас одна только, user, и в ней нет внешних ключей.
Если запускать функциональные тесты с анализом покрытия кода
то после того как тесты прошли, появляется ошибка (без анализатора всё нормально)
и еще после того как проходят acceptance тесты, не могу посмотреть фэйлы и ошибки, тоже выскакивает
Дмитрий ЕлисеевMySQL server has gone away - значит MySQL отключился по таймауту.
РоманДобрый вечер.
Дмитрий, почему не могу обнаружить после завершения
файл _output/coverage/index.html
В _output даже папки coverage нет.
Где-то прописать нужно? Где?
Дмитрий ЕлисеевА на свежем yii2-app-basic появляется?
РоманДмитрий, добрый день.
Прошу прощения за продолжение оборвавшегося диалога, небыло доступа к ПК.
Да, на свежем yii2-app-basic появляется.
Где я мог ошибиться?
Дмитрий ЕлисеевА в codeception.yml секцию coverage настроили?
РоманДа всё настроено.
Вообщем пропустил этот момент временно. Перешёл к другой главе. Некоторое время спустя. Попробовал протестить и всё появилось. Видимо с Гита скопировал часть кода, относящуюся к следующей главе.
P.S. давно Вас не было слышно...
ЮрийЗдравствуйте!
Подскажите, почему не проходит часть тестов. Запускаю так codecept run unit.
Вываливаются ошибки вида:
Результат
Дмитрий ЕлисеевУберите опцию --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
А как запустить определенный класс/метод на тест, а не все тесты из папки?
Заранее большое спасибо!
Дмитрий Елисеев
СергейДмитрий, спасибо огромное!
КостяА в функциональных тестах 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, пишу команду:
Начинается запуск:
И на этом моменте запуск бесконечно зависает.
Как можно это поправить? Или хотя бы понять в чем проблема?
АлександрПопробовал использовать версию 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
АлександрРазобрался.
Весьма не очевидный для новичка момент:
Запускается строка
Дальше нужно открыть новое окно консоли и там уже запустить 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Добрый день!
Помогите устранить ошибку, не могу запустить тесты
Спасибо!
Дмитрий ЕлисеевОбновите вендоры. Может быть поможет.
СергейЭто не помогает
Дмитрий ЕлисеевЗначит что-то уже сильно устарело.
СергейИспользуйте 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/, а тот, на который указывает символическая ссылка.
Спасибо