|
| 1 | +--- |
| 2 | +layout: page |
| 3 | +title: Codeception for Yii2 |
| 4 | +hero: yii_hero.html |
| 5 | +sidebar: | |
| 6 | +
|
| 7 | + ## Codeception Tests |
| 8 | +
|
| 9 | + * **Recommended** by Yii core team |
| 10 | + * Pre-installed for basic and advanced application templates |
| 11 | + * Official Yii framework integration |
| 12 | +
|
| 13 | + ## Reference |
| 14 | +
|
| 15 | + * [Yii2 Module](/docs/modules/Yii2) |
| 16 | + * [Yii Basic Template](https://github.com/yiisoft/yii2-app-basic) |
| 17 | + * [Yii Advanced Temlate](https://github.com/yiisoft/yii2-app-advanced) |
| 18 | +
|
| 19 | +--- |
| 20 | + |
| 21 | +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. |
| 22 | + |
| 23 | +## Yii Basic |
| 24 | + |
| 25 | +Once you created a project from a [basic template](https://github.com/yiisoft/yii2-app-basic/) you should see folder `tests` and `codeception.yml` configuration file. From start there are functional and unit test suites. |
| 26 | + |
| 27 | +Run them by executing in terminal: |
| 28 | + |
| 29 | +``` |
| 30 | +composer exec codecept run |
| 31 | +``` |
| 32 | + |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +### Unit Tests |
| 37 | + |
| 38 | +Unit tests are located in `tests/unit` directory and are supposed to contain all kind of unit and intgration testing. |
| 39 | + |
| 40 | +Each test case extends `Codeception\Test\Unit` class, which is stndard Codeception format for unit testing. |
| 41 | + 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: |
| 42 | + |
| 43 | +```yaml |
| 44 | +modules: |
| 45 | + enabled: |
| 46 | + - Yii2: |
| 47 | + part: [orm, email] |
| 48 | +``` |
| 49 | +
|
| 50 | +This module starts Yii application for a test case and provides additional helper methods to simplify testing. It has only `orm` and `email` parts in order to exclude methods needed for functional testing only. |
| 51 | + |
| 52 | +By accessing `$this->tester` class inside a test case you can use methods of [Yii2 module](http://codeception.com/docs/modules/Yii2). So if you have orm and email parts enabled so you can call methods belonging from these parts: |
| 53 | + |
| 54 | +```php |
| 55 | +<?php |
| 56 | +// insert records in database |
| 57 | +$this->tester->haveRecord('app/model/User', ['username' => 'davert']); |
| 58 | +// check records in database |
| 59 | +$this->tester->seeRecord('app/model/User', ['username' => 'davert']); |
| 60 | +// test email was sent |
| 61 | +$this->tester->seeEmailIsSent(); |
| 62 | +// get a last sent emails |
| 63 | +$this->tester->grabLastSentEmail(); |
| 64 | +``` |
| 65 | + |
| 66 | +If you enable `fixtures` part you will also get methods to load and use fixtures in your tests: |
| 67 | + |
| 68 | +```php |
| 69 | +<?php |
| 70 | +// load fixtures |
| 71 | +$this->tester->haveFixtures([ |
| 72 | + 'user' => [ |
| 73 | + 'class' => UserFixture::className(), |
| 74 | + // fixture data located in tests/_data/user.php |
| 75 | + 'dataFile' => codecept_data_dir() . 'user.php' |
| 76 | + ] |
| 77 | +]); |
| 78 | +// get first user from fixtures |
| 79 | +$this->tester->grabFixture('user', 0); |
| 80 | +``` |
| 81 | + |
| 82 | +If `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](http://codeception.com/docs/06-ModulesAndHelpers#Helpers). |
| 83 | + |
| 84 | +<div class="alert alert-warning"> |
| 85 | + <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> |
| 86 | + Continue to <a href="http://codeception.com/docs/05-UnitTests">Unit Testing Guide »</a> |
| 87 | +</div> |
| 88 | + |
| 89 | + |
| 90 | +### Functional Tests |
| 91 | + |
| 92 | +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: |
| 93 | + |
| 94 | +```php |
| 95 | +<?php |
| 96 | +$I->amOnPage(['site/contact']); |
| 97 | +$I->submitForm('#contact-form', []); |
| 98 | +$I->expectTo('see validations errors'); |
| 99 | +$I->see('Contact', 'h1'); |
| 100 | +$I->see('Name cannot be blank'); |
| 101 | +$I->see('Email cannot be blank'); |
| 102 | +$I->see('Subject cannot be blank'); |
| 103 | +$I->see('Body cannot be blank'); |
| 104 | +``` |
| 105 | + |
| 106 | +This way you not only test the ContactForm on a site but actual output of applicaiton that user sees. |
| 107 | +Codeception provides standard set of actions like `amOnPage`, `submitForm`, `see` for testing. Yii2 module provdes special methods, like `amLoggedInAs` (for fast authentication), `haveRecord`, `seeRecord`, `seeEmailIsSent` and others. They all are listed in [module reference](http://codeception.com/docs/modules/Yii2). |
| 108 | + |
| 109 | +Functional tests should be written inside [Cest files](http://codeception.com/docs/07-AdvancedUsage#Cest-Classes), which is a scenario-driven test format of Codeception. You can easily create a new test by running: |
| 110 | + |
| 111 | +``` |
| 112 | +composer exec codecept g:cest functional MyNewScenarioCest |
| 113 | +``` |
| 114 | +
|
| 115 | +<div class="alert alert-warning"> |
| 116 | + <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> |
| 117 | + Functional tests are really powerful and simple. They are highly <strong>recommended to use</strong> for any Yii application.<br> |
| 118 | + Continue to <a href="http://codeception.com/docs/04-FunctionalTests">Functional Testing Guide »</a> |
| 119 | +</div> |
| 120 | +
|
| 121 | +### API Tests |
| 122 | +
|
| 123 | +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 |
| 124 | +
|
| 125 | +``` |
| 126 | +composer exec codecept g:suite api |
| 127 | +``` |
| 128 | +
|
| 129 | +You will need to enable `REST`, `Yii2` module in `tests/api.suite.yml`: |
| 130 | +
|
| 131 | +```yaml |
| 132 | +class_name: ApiTester |
| 133 | +modules: |
| 134 | + enabled: |
| 135 | + - REST: |
| 136 | + url: /api/v1 |
| 137 | + depends: Yii2 |
| 138 | + - \ApiBundle\Helper\Api |
| 139 | + config: |
| 140 | + - Yii2 |
| 141 | +
|
| 142 | +``` |
| 143 | + |
| 144 | +Yii2 module actions like `amOnPage` or `see` should not be available for testing API. This is why Yii2 module is not enabled but declared with `depends` for REST module. |
| 145 | + |
| 146 | +<div class="alert alert-warning"> |
| 147 | + <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> |
| 148 | + Continue to <a href="http://codeception.com/docs/10-WebServices#REST">REST API Testing Guide »</a>. |
| 149 | +</div> |
| 150 | + |
| 151 | +### Acceptance Tests |
| 152 | + |
| 153 | +From a test perspective acceptance tests do the same as functional tests. They test the user interaction with application but in this case using *real* browser and web server. They are much slower and much more fragile. They should not duplicate functional tests in matter of testing functionality but should be used for testing the UI of your application. If you are unsure which tests should be acceptance and which are functional, write acceptance tests for JavaScript-rich applications, where UI highly depends on a browser processing. You can also use acceptance tests for happy-path scenarios, just to ensure that a real user using a real browser achieve the same results you expect in functional tests. |
| 154 | + |
| 155 | +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 `acceptance.suite.yml.example` to `acceptance.suite.yml` |
| 156 | + |
| 157 | +``` |
| 158 | +mv tests/acceptance.suite.yml.example tests/acceptance.suite.yml |
| 159 | +``` |
| 160 | + |
| 161 | +Basic template uses `codeception/base` package which doesn't contain `facebook/webdriver` library required to run acceptance tests. Please change `codeception/base` to `codeception/codeception` in `composer.json` and run the update command. |
| 162 | + |
| 163 | +Then you will need to launch application server in test mode: |
| 164 | + |
| 165 | +``` |
| 166 | +./tests/bin/yii serve |
| 167 | +``` |
| 168 | + |
| 169 | +and start a [Selenium Server or PhantomJS](http://codeception.com/docs/modules/WebDriver#Local-Testing). 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: |
| 170 | + |
| 171 | +```yml |
| 172 | +# config at tests/acceptance.yml |
| 173 | +modules: |
| 174 | + enabled: |
| 175 | + - WebDriver: |
| 176 | + url: http://127.0.0.1:8080/ |
| 177 | + browser: firefox |
| 178 | + - Yii2: |
| 179 | + part: [orm, fixtures] # allow to use AR methods |
| 180 | + cleanup: false # don't wrap test in transaction |
| 181 | + entryScript: index-test.php |
| 182 | +``` |
| 183 | +
|
| 184 | +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 `entryScript` and `entryUrl` values to change the default host and script configuration for your app. |
| 185 | + |
| 186 | +Similar as for functional tests it is recommended to use Cest format for acceptance testing: |
| 187 | + |
| 188 | +``` |
| 189 | +composer exec codecept g:cest acceptance MyNewScenarioCest |
| 190 | +``` |
| 191 | + |
| 192 | +<div class="alert alert-warning"> |
| 193 | + <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> |
| 194 | + Continue to <a href="http://codeception.com/docs/03-AcceptanceTests">Acceptance Testing Guide »</a> |
| 195 | +</div> |
| 196 | + |
| 197 | +## Yii Advanced |
| 198 | + |
| 199 | +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 `frontend`, `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. |
| 200 | + |
| 201 | +!()[/images/yii-advenced-tests.png] |
| 202 | + |
| 203 | +Tests also include namespaces for testcase classes and testers to avoid conflicts between tests from different applications. |
| 204 | + |
| 205 | +<div class="alert alert-warning"> |
| 206 | + <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> |
| 207 | + Learn more about <a href="http://codeception.com/docs/08-Customization#One-Runner-for-Multiple-Applications">testing multiple applications »</a> |
| 208 | +</div> |
| 209 | + |
| 210 | +## Configuration |
| 211 | + |
| 212 | +It is important to understand how Yii2 module is configured to run the application. The only required parameter for Yii2 is `configFile`. This file with configuration for test environment of Yii application. It should be stored merge original application config overriding `id` value and provide different database for testing: |
| 213 | + |
| 214 | +```php |
| 215 | +<?php |
| 216 | +$config = yii\helpers\ArrayHelper::merge( |
| 217 | + require(__DIR__ . '/main.php'), |
| 218 | + require(__DIR__ . '/main-local.php'), |
| 219 | + [ |
| 220 | + 'id' => 'app-tests', |
| 221 | + 'components' => [ |
| 222 | + 'db' => [ |
| 223 | + 'dsn' => 'mysql:host=localhost;dbname=yii_app_test', |
| 224 | + ] |
| 225 | + ] |
| 226 | + ] |
| 227 | +); |
| 228 | +return $config; |
| 229 | +``` |
| 230 | + |
| 231 | +It is important to override database configuration so running tests won't affect your development or production database. Test config is recommended to store in `config` folder of application. A relative path to it from `codeception.yml` is required. In basic and advanced applications `configFile` is defined in global configuration file: |
| 232 | + |
| 233 | +```yml |
| 234 | +# inside codeception.yml |
| 235 | +modules: |
| 236 | + config: |
| 237 | + Yii2: |
| 238 | + configFile: 'config/test.php' |
| 239 | +``` |
| 240 | + |
| 241 | +This way we don't need to provide test config for each defined suite. |
| 242 | + |
| 243 | +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. |
0 commit comments