Browse Source

Updated testing docs [skip ci]

tags/2.0.13
Alexander Makarov 7 years ago committed by GitHub
parent
commit
5a01c09270
  1. 14
      docs/guide/test-acceptance.md
  2. 6
      docs/guide/test-environment-setup.md
  3. 148
      docs/guide/test-fixtures.md
  4. 19
      docs/guide/test-functional.md
  5. 21
      docs/guide/test-overview.md
  6. 20
      docs/guide/test-unit.md

14
docs/guide/test-acceptance.md

@ -1,11 +1,17 @@
Acceptance Tests
================
> Note: This section is under development.
Acceptance test verifies scenarios from a user's perspective. The application tested is accessed via either PhpBrowser or
a real browser. In both cases the browsers are communicating via HTTP so application should be served via web server.
Acceptance testing is implemented with the help of Codeception framework which has a nice documentation about it:
- [Codeception for Yii framework](http://codeception.com/for/yii)
- [Codeception Acceptance Tests](http://codeception.com/docs/03-AcceptanceTests)
Running basic and advanced template acceptance tests
----------------------------------------------------
## Running basic and advanced template tests
If you've started with advanced template, please refer to ["testing" guide](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md)
for more details about running tests.
Please refer to instructions provided in `apps/advanced/tests/README.md` and `apps/basic/tests/README.md`.
If you've started with basic template, check its [README "testing" section](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing).

6
docs/guide/test-environment-setup.md

@ -4,9 +4,9 @@ Testing environment setup
Yii 2 has officially maintained integration with [`Codeception`](https://github.com/Codeception/Codeception) testing
framework that allows you to create the following test types:
- [Unit testing](test-unit.md) - verifies that a single unit of code is working as expected;
- [Functional testing](test-functional.md) - verifies scenarios from a user's perspective via browser emulation;
- [Acceptance testing](test-acceptance.md) - verifies scenarios from a user's perspective in a browser.
- [Unit](test-unit.md) - verifies that a single unit of code is working as expected;
- [Functional](test-functional.md) - verifies scenarios from a user's perspective via browser emulation;
- [Acceptance](test-acceptance.md) - verifies scenarios from a user's perspective in a browser.
Yii provides ready to use test sets for all three test types in both
[`yii2-basic`](https://github.com/yiisoft/yii2-app-basic) and

148
docs/guide/test-fixtures.md

@ -3,7 +3,8 @@ Fixtures
Fixtures are an important part of testing. Their main purpose is to set up the environment in a fixed/known state
so that your tests are repeatable and run in an expected way. Yii provides a fixture framework that allows
you to define your fixtures precisely and use them easily.
you to define your fixtures precisely and use them easily both when running your tests with Codeception
and independently.
A key concept in the Yii fixture framework is the so-called *fixture object*. A fixture object represents
a particular aspect of a test environment and is an instance of [[yii\test\Fixture]] or its child class. For example,
@ -15,8 +16,7 @@ When a fixture is being loaded, the fixtures it depends on will be automatically
and when the fixture is being unloaded, the dependent fixtures will be unloaded AFTER the fixture.
Defining a Fixture
------------------
## Defining a Fixture
To define a fixture, create a new class by extending [[yii\test\Fixture]] or [[yii\test\ActiveFixture]].
The former is best suited for general purpose fixtures, while the latter has enhanced features specifically
@ -105,31 +105,35 @@ In the above, we have shown how to define a fixture about a DB table. To define
[[yii\test\Fixture]] and override the [[yii\test\Fixture::load()|load()]] and [[yii\test\Fixture::unload()|unload()]] methods.
Using Fixtures
--------------
## Using Fixtures
If you are using [Codeception](http://codeception.com/) to test your code, you should consider using
the `yii2-codeception` extension which has built-in support for loading and accessing fixtures.
If you are using other testing frameworks, you may use [[yii\test\FixtureTrait]] in your test cases
to achieve the same goal.
If you are using [Codeception](http://codeception.com/) to test your code, you can use built-in support for loading
and accessing fixtures.
In the following we will describe how to write a `UserProfile` unit test class using `yii2-codeception`.
If you are using other testing frameworks, you may use [[yii\test\FixtureTrait]] in your
test cases to achieve the same goal.
In your unit test class extending [[yii\codeception\DbTestCase]] or [[yii\codeception\TestCase]],
declare which fixtures you want to use in the [[yii\test\FixtureTrait::fixtures()|fixtures()]] method. For example,
In the following we will describe how to write a `UserProfile` unit test class using Codeception.
In your unit test class extending `\Codeception\Test\Unit` either declare fixtures you want to use in the
`_fixtures()` method or use `haveFixtures()` method of an actor directly. For example,
```php
namespace app\tests\unit\models;
use yii\codeception\DbTestCase;
use app\tests\fixtures\UserProfileFixture;
class UserProfileTest extends DbTestCase
class UserProfileTest extends \Codeception\Test\Unit
{
public function fixtures()
public function _fixtures()
{
return [
'profiles' => UserProfileFixture::className(),
'profiles' => [
'class' => UserProfileFixture::className(),
// fixture data located in tests/_data/user.php
'dataFile' => codecept_data_dir() . 'user.php'
],
];
}
@ -137,56 +141,32 @@ class UserProfileTest extends DbTestCase
}
```
The fixtures listed in the `fixtures()` method will be automatically loaded before running every test method
in the test case and unloaded after finishing every test method. And as we described before, when a fixture is
being loaded, all its dependent fixtures will be automatically loaded first. In the above example, because
`UserProfileFixture` depends on `UserFixture`, when running any test method in the test class,
two fixtures will be loaded sequentially: `UserFixture` and `UserProfileFixture`.
The fixtures listed in the `_fixtures()` method will be automatically loaded before a test is executed. And as we
described before, when a fixture is being loaded, all its dependent fixtures will be automatically loaded first.
In the above example, because `UserProfileFixture` depends on `UserFixture`, when running any test method in the test
class, two fixtures will be loaded sequentially: `UserFixture` and `UserProfileFixture`.
When specifying fixtures in `fixtures()`, you may use either a class name or a configuration array to refer to
a fixture. The configuration array will let you customize the fixture properties when the fixture is loaded.
When specifying fixtures for both `_fixtures()` and `haveFixtures()`, you may use either a class name
or a configuration array to refer to a fixture. The configuration array will let you customize
the fixture properties when the fixture is loaded.
You may also assign an alias to a fixture. In the above example, the `UserProfileFixture` is aliased as `profiles`.
In the test methods, you may then access a fixture object using its alias. For example, `$this->profiles` will
return the `UserProfileFixture` object.
In the test methods, you may then access a fixture object using its alias in `grabFixture()` method. For example,
```php
$profile = $I->grabFixture('profiles', 'user1');` will return the `UserProfileFixture` object.
Because `UserProfileFixture` extends from `ActiveFixture`, you may further use the following syntax to access
the data provided by the fixture:
```php
// returns the data row aliased as 'user1'
$row = $this->profiles['user1'];
// returns the UserProfile model corresponding to the data row aliased as 'user1'
$profile = $this->profiles('user1');
// traverse every data row in the fixture
foreach ($this->profiles as $row) ...
$profile = $I->grabFixture('profiles', 'user1');
// traverse data in the fixture
foreach ($I->grabFixture('profiles') as $profile) ...
```
> Info: `$this->profiles` is still of `UserProfileFixture` type. The above access features are implemented
> through PHP magic methods.
Defining and Using Global Fixtures
----------------------------------
The fixtures described above are mainly used by individual test cases. In most cases, you also need some global
fixtures that are applied to ALL or many test cases. An example is [[yii\test\InitDbFixture]] which does
two things:
* Perform some common initialization tasks by executing a script located at `@app/tests/fixtures/initdb.php`;
* Disable the database integrity check before loading other DB fixtures, and re-enable it after other DB fixtures are unloaded.
Using global fixtures is similar to using non-global ones. The only difference is that you declare these fixtures
in [[yii\codeception\TestCase::globalFixtures()]] instead of `fixtures()`. When a test case loads fixtures, it will
first load global fixtures and then non-global ones.
By default, [[yii\codeception\DbTestCase]] already declares `InitDbFixture` in its `globalFixtures()` method.
This means you only need to work with `@app/tests/fixtures/initdb.php` if you want to do some initialization work
before each test. You may otherwise simply focus on developing each individual test case and the corresponding fixtures.
Organizing Fixture Classes and Data Files
-----------------------------------------
## Organizing Fixture Classes and Data Files
By default, fixture classes look for the corresponding data files under the `data` folder which is a sub-folder
of the folder containing the fixture class files. You can follow this convention when working with simple projects.
@ -221,34 +201,7 @@ In this way you will avoid collision of fixture data files between tests and use
The similar hierarchy can be used to organize fixture class files. Instead of using `data` as the root directory, you may
want to use `fixtures` as the root directory to avoid conflict with the data files.
Summary
-------
> Note: This section is under development.
In the above, we have described how to define and use fixtures. Below we summarize the typical workflow
of running unit tests related with DB:
1. Use `yii migrate` tool to upgrade your test database to the latest version;
2. Run a test case:
- Load fixtures: clean up the relevant DB tables and populate them with fixture data;
- Perform the actual test;
- Unload fixtures.
3. Repeat Step 2 until all tests finish.
**To be cleaned up below**
Managing Fixtures
=================
> Note: This section is under development.
>
> todo: this tutorial may be merged with the above part of test-fixtures.md
Fixtures are important part of testing. Their main purpose is to populate you with data that needed by testing
different cases. With this data using your tests becoming more efficient and useful.
## Managing fixtures with `yii fixture`
Yii supports fixtures via the `yii fixture` command line tool. This tool supports:
@ -256,10 +209,8 @@ Yii supports fixtures via the `yii fixture` command line tool. This tool support
* Unloading fixtures in different ways (usually it is clearing storage);
* Auto-generating fixtures and populating it with random data.
Fixtures format
---------------
### Fixtures data format
Fixtures are objects with different methods and configurations, refer to official [documentation](https://github.com/yiisoft/yii2/blob/master/docs/guide/test-fixtures.md) on them.
Lets assume we have fixtures data to load:
```
@ -287,8 +238,7 @@ fixture, then this data will be applied to `users` mongodb collection. In order
Above fixture example was auto-generated by `yii2-faker` extension, read more about it in these [section](#auto-generating-fixtures).
Fixture classes name should not be plural.
Loading fixtures
----------------
### Loading fixtures
Fixture classes should be suffixed by `Fixture` class. By default fixtures will be searched under `tests\unit\fixtures` namespace, you can
change this behavior with config or command options. You can exclude some fixtures due load or unload by specifying `-` before its name like `-User`.
@ -332,8 +282,7 @@ yii fixture User --namespace='alias\my\custom\namespace'
yii fixture User --globalFixtures='some\name\space\Custom'
```
Unloading fixtures
------------------
### Unloading fixtures
To unload fixture, run the following command:
@ -354,8 +303,8 @@ yii fixture/unload "*, -DoNotUnloadThisOne"
Same command options like: `namespace`, `globalFixtures` also can be applied to this command.
Configure Command Globally
--------------------------
### Configure Command Globally
While command line options allow us to configure the migration command
on-the-fly, sometimes we may want to configure the command once for all. For example you can configure
different migration path as follows:
@ -373,9 +322,20 @@ different migration path as follows:
]
```
Auto-generating fixtures
------------------------
### Auto-generating fixtures
Yii also can auto-generate fixtures for you based on some template. You can generate your fixtures with different data on different languages and formats.
This feature is done by [Faker](https://github.com/fzaninotto/Faker) library and `yii2-faker` extension.
See extension [guide](https://github.com/yiisoft/yii2-faker) for more docs.
## Summary
In the above, we have described how to define and use fixtures. Below we summarize the typical workflow
of running unit tests related with DB:
1. Use `yii migrate` tool to upgrade your test database to the latest version;
2. Run a test case:
- Load fixtures: clean up the relevant DB tables and populate them with fixture data;
- Perform the actual test;
- Unload fixtures.
3. Repeat Step 2 until all tests finish.

19
docs/guide/test-functional.md

@ -1,11 +1,22 @@
Functional Tests
================
> Note: This section is under development.
Functional test verifies scenarios from a user's perspective. It is similar to [acceptance test](test-acceptance.md)
but instead of communicating via HTTP it is filling up environment such as POST and GET parameters and then executes
application instance right from the code.
Functional tests are generally faster than acceptance tests and are providing detailed stack traces on failures.
As a rule of thumb, they should be preferred unless you have a special web server setup or complex UI powered by
JavaScript.
Functional testing is implemented with the help of Codeception framework which has a nice documentation about it:
- [Codeception for Yii framework](http://codeception.com/for/yii)
- [Codeception Functional Tests](http://codeception.com/docs/04-FunctionalTests)
Running basic and advanced template functional tests
----------------------------------------------------
## Running basic and advanced template tests
If you've started with advanced template, please refer to ["testing" guide](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md)
for more details about running tests.
Please refer to instructions provided in `apps/advanced/tests/README.md` and `apps/basic/tests/README.md`.
If you've started with basic template, check its [README "testing" section](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing).

21
docs/guide/test-overview.md

@ -6,13 +6,13 @@ For example, when we write a class in PHP, we may debug it step by step or simpl
the implementation works according to our initial plan. In the case of a web application, we're entering some test data
in forms to ensure the page interacts with us as expected.
The testing process could be automated so that each time when we need to verify something, we just need to call up the code that does it for us. The code that verifies the result matches
what we've planned is called *test* and the process of its creation and further execution is known as *automated testing*,
which is the main topic of these testing chapters.
The testing process could be automated so that each time when we need to verify something, we just need to call up
the code that does it for us. The code that verifies the result matches what we've planned is called *test* and
the process of its creation and further execution is known as *automated testing*, which is the main topic of these
testing chapters.
Developing with tests
------------------
## Developing with tests
Test-Driven Development (TDD) and Behavior-Driven Development (BDD) are approaches of developing
software by describing behavior of a piece of code or the whole feature as a set of scenarios or tests before
@ -37,18 +37,14 @@ The reason to create tests before doing any implementation is that it allows us
and fully dive into "how to do it" afterwards. Usually it leads to better abstractions and easier test maintenance when
it comes to feature adjustments or less coupled components.
So to sum up the pros of such an approach are the following:
So to sum up the advantages of such approach are the following:
- Keeps you focused on one thing at a time which results in improved planning and implementation.
- Results in test-covering more features in greater detail i.e. if tests are OK most likely nothing's broken.
In the long term it usually gives you a good time-saving effect.
> Tip: If you want to know more about the principles for gathering software requirements and modeling the subject
> matter it's good to learn [Domain Driven Development (DDD)](https://en.wikipedia.org/wiki/Domain-driven_design).
When and how to test
------------------
## When and how to test
While the test first approach described above makes sense for long term and relatively complex projects it could be overkill
for simpler ones. There are some indicators of when it's appropriate:
@ -70,7 +66,6 @@ In some cases any form of automated testing could be overkill:
Still if you have time it's good to automate testing in these cases as well.
Further reading
-------------
## Further reading
- Test Driven Development: By Example / Kent Beck. ISBN: 0321146530.

20
docs/guide/test-unit.md

@ -1,28 +1,24 @@
Unit Tests
==========
> Note: This section is under development.
A unit test verifies that a single unit of code is working as expected. In object-oriented programming, the most basic
code unit is a class. A unit test thus mainly needs to verify that each of the class interface methods works properly.
That is, given different input parameters, the test verifies the method returns expected results.
Unit tests are usually developed by people who write the classes being tested.
A unit test verifies that a single unit of code is working as expected. That is, given different input parameters,
the test verifies the class method returns expected results. Unit tests are usually developed by people who write the
classes being tested.
Unit testing in Yii is built on top of PHPUnit and, optionally, Codeception so it's recommended to go through their docs:
- [PHPUnit docs starting from chapter 2](http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html).
- [Codeception Unit Tests](http://codeception.com/docs/05-UnitTests).
- [Codeception for Yii framework](http://codeception.com/for/yii)
- [Codeception Unit Tests](http://codeception.com/docs/05-UnitTests)
- [PHPUnit docs starting from chapter 2](http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html)
Running basic and advanced template tests
-----------------------------------------
## Running basic and advanced template tests
If you've started with advanced template, please refer to ["testing" guide](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md)
for more details about running tests.
If you've started with basic template, check its [README "testing" section](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing).
Framework unit tests
--------------------
## Framework unit tests
If you want to run unit tests for Yii framework itself follow
"[Getting started with Yii 2 development](https://github.com/yiisoft/yii2/blob/master/docs/internals/getting-started.md)".

Loading…
Cancel
Save