Yii Framework provides basic and advanced application templates. Both include sample Codeception tests, thus to start with Codeception you need to start new Yii project from a one of those templates.
Once you created a project from a basic template you should see folder
codeception.yml configuration file. From start there are functional and unit test suites.
Run them by executing in terminal:
Unit tests are located in
tests/unit directory and are supposed to contain all kind of unit and integration testing.
Each test case extends
Codeception\Test\Unit class, which is standard Codeception format for unit testing.
It is pretty hard to develop completely isolated unit tests in Yii, so an application is bootstrapped before each test case. Tests are configured in
tests/unit.suite.yml file with Yii2 module enabled:
modules: enabled: - Yii2: part: [orm, email]
This module starts Yii application for a test case and provides additional helper methods to simplify testing. It has only
$this->tester class inside a test case you can use methods of Yii2 module. So if you have orm and email parts enabled so you can call methods belonging from these parts:
<?php // insert records in database $this->tester->haveRecord('app/model/User', ['username' => 'davert']); // check records in database $this->tester->seeRecord('app/model/User', ['username' => 'davert']); // test email was sent $this->tester->seeEmailIsSent(); // get a last sent emails $this->tester->grabLastSentEmail();
If you enable
fixtures part you will also get methods to load and use fixtures in your tests:
<?php // load fixtures $this->tester->haveFixtures([ 'user' => [ 'class' => UserFixture::className(), // fixture data located in tests/_data/user.php 'dataFile' => codecept_data_dir() . 'user.php' ] ]); // get first user from fixtures $this->tester->grabFixture('user', 0);
Yii2 module is enabled you can safely call
Yii::$app inside a test, as application is initialized and cleaned up after a test. If you want to add your helper methods or custom assertions for your test case you should not extend
Codeception\Test\Unit but write your own separate Helper class.
When it comes to test real features of web applications you can’t go with unit testing only. You want to test how application handles the requests, what responses it provides, what data is saved to database and so on. To test application in near user environment but without launching real webserver or a browser you can use functional tests. They are far more simpler than unit tests in a way they are written. They describe interaction scenario in a simple DSL so you don’t need to deal with application directly but describe actions from a user’s perspective:
<?php $I->amOnPage(['site/contact']); $I->submitForm('#contact-form', ); $I->expectTo('see validations errors'); $I->see('Contact', 'h1'); $I->see('Name cannot be blank'); $I->see('Email cannot be blank'); $I->see('Subject cannot be blank'); $I->see('Body cannot be blank');
This way you not only test the ContactForm on a site but actual output of application that user sees.
Codeception provides standard set of actions like
see for testing. Yii2 module provides special methods, like
amLoggedInAs (for fast authentication),
seeEmailIsSent and others. They all are listed in module reference.
Functional tests should be written inside Cest files, which is a scenario-driven test format of Codeception. You can easily create a new test by running:
./vendor/bin/codecept g:cest functional MyNewScenarioCest
API tests are not included in any Yii templates so you need to set up them manually if you developing a web service. API testing is done at functional testing level but instead of testing HTML responses on user actions, they test requests and responses via protocols like REST or SOAP. To start writing api tests you should create a suite for them
./vendor/bin/codecept g:suite api
You will need to enable
Yii2 module in
class_name: ApiTester modules: enabled: - REST: url: /api/v1 depends: Yii2 - \ApiBundle\Helper\Api config: - Yii2
Yii2 module actions like
see should not be available for testing API. This is why Yii2 module is not enabled but declared with
depends for REST module.
By default in basic application acceptance tests are disabled (as they require web server, Selenium Server and browser to be running). You can easily enable them by renaming
mv tests/acceptance.suite.yml.example tests/acceptance.suite.yml
Basic template uses
codeception/base package which doesn’t contain
facebook/webdriver library required to run acceptance tests. Please change
composer.json and run the update command.
Then you will need to launch application server in test mode:
and start a Selenium Server. For acceptance WebDriver module is used. Please check its reference to learn how to work with it. Unlike Yii2 module it does know nothing about your application, so if you want to use features of Yii like fixtures for acceptance testing, you should check that enable Yii2 module is enabled as well:
# config at tests/acceptance.yml modules: enabled: - WebDriver: url: http://127.0.0.1:8080/ browser: firefox - Yii2: part: [orm, fixtures] # allow to use AR methods cleanup: false # don't wrap test in transaction entryScript: index-test.php
As it was said, functional and acceptance tests are similar, so in order to avoid conflicts with these modules you should load only a part of Yii2 module which you really need. You must also set
cleanup: false so Yii2 changes to database to be saved and used by application running on web server. Use
entryUrl values to change the default host and script configuration for your app.
Similar as for functional tests it is recommended to use Cest format for acceptance testing:
./vendor/bin/codecept g:cest acceptance MyNewScenarioCest
Advanced template also has Codeception preinstalled with examples of unit, functional, and acceptance tests. However, you won’t find
tests folder in a root of application. This because every application
backend, and their
common has their own tests. This is done to have tests and source to be placed in a same location. To run all tests from all application at once, you should execute
codecept run from a project root. Global
codeception.yml config was written to include tests from all applications.
Tests also include namespaces for testcase classes and testers to avoid conflicts between tests from different applications.
To start you need to install Codeception via Composer
composer require "codeception/codeception" --dev
Create basic test suites
Enable module Yii2 for functional tests inside
# functional.suite.yml modules: enabled: - Yii2: configFile: #insert path to config file
The only required parameter for Yii2 module is
configFile. This file with configuration for test configuration of Yii application. It should merge original application config overriding
id value and provide different database for testing:
<?php // config/test.php $config = yii\helpers\ArrayHelper::merge( require(__DIR__ . '/main.php'), require(__DIR__ . '/main-local.php'), [ 'id' => 'app-tests', 'components' => [ 'db' => [ 'dsn' => 'mysql:host=localhost;dbname=yii_app_test', ] ] ] ); return $config;
Test config is recommended to store in
config folder of application. You should provide path to test config relatively to
Please also make sure that
YII_ENV constant is set to
test as it is done in
tests/_bootstrap.php file of basic and advanced app templates.
Once you configured functional tests it should be easy to create setup for unit and acceptance tests, as it is described in this guide.
In basic and advanced application templates
configFile is defined in global configuration file:
# inside codeception.yml modules: config: Yii2: configFile: 'config/test.php'
This way we don’t need to provide test config for each defined suite.