📜 ⬆️ ⬇️

Testing with Сodeception for dummies: 3 types of tests

The purpose of this article I set to show people who are not familiar with testing how you can really quickly start testing, gathering everything in one place with a minimum of water and in Russian. Let it be very primitive. Let not very interesting to people who already live on TDD, SOLID and other principles. But after reading to the end, anyone can make their first confident step into the world of testing.


We will consider Acceptance, Functional and Unit Tests or Unit Tests.



Also, this article was prompted by the fact that many articles called "Codeception" are actually just one acceptace test.
PS: I warn you right away that I am not a pro and I can make mistakes in everything.

Installing Composer & Codeception


If you are confused by phrases


$ composer require "codeception/codeception:*" $ alias cept="./vendor/bin/codecept" 

then under the cut, I will tell in more detail. Or - go ahead.

To get started, we need a great tool Composer. In most projects, it will already be installed. But installing it is also not a problem. All options are listed on his official page: https://getcomposer.org/download/ The most commonplace and easiest way is to scroll down the page and simply download the * .phar file to the root of your project.


Best practitioners will tell you that doing so is bad. You need to place it in / etc / bin, give permissions to execute and rename to composer. Listen to them when you finish the article to the end.


The second step in setting up Composer, as well as a very frequent answer, what to do when Composer broke down: update / install an FXP plugin. He "lives" at: https://packagist.org/packages/fxp/composer-asset-plugin And is often installed with the command:
$ php composer.phar global require "fxp/composer-asset-plugin:~1.4.2"
Please note that the version must enter the one that will be displayed on the site at the time of reading this article.


The final setting before starting work is to set yourself a Codeception using Composer:
$ php composer.phar require "codeception/codeception:*"


After that, the Codeception executable file is available for us in the ./vendor/bin/codecept subdirectory for Linux and ./vendor/bin/codecept.bat for Windows. Type this before each launch for a long time. Therefore, we make abbreviations:
For Linux: $ alias cept="./vendor/bin/codecept"
For Windows, in the root of the project (from where we will run the tests) we create a new bat file: cept.bat


 @echo off @setlocal set CODECEPT_PATH=vendor/bin/ "%CODECEPT_PATH%codecept.bat" %* @endlocal 

After that, the cept command, in the console, should return the help-page for Codeception. And if you want to run cept.bat from any directory, look towards the PATH directive.


And a couple of tips on this topic:
Removing a package from the composer: $ php composer.phar remove codeception/codeception
If you encounter a problem: "Fatal error: Allowed memory size of 12345678 bytes exhausted" . "Fatal error: Allowed memory size of 12345678 bytes exhausted" Composer will prompt the link on which a slightly modified call will be written: $ php -d memory_limit=-1 composer.phar {_}


Creating the first test: Acceptance or Acceptance


Now we are one step away from our first test. We’ll check that our site has a main page and an About page. That they return the correct response code "200" and contain keywords.


Actually - this is the essence of acceptance tests: check what is available to a person who is far from programming: viewing the contents of the page, trying to log in, etc.


$ cept bootstrap - doing a one-time initialization, after the first installation
$ cept generate:cept acceptance SmokeTest - create the first test script


Open the tests / acceptance / SmokeTestCept.php and append to the existing two lines of new AcceptanceTester and wantTo your own. At the exit we should be able to:


 $I = new AcceptanceTester($scenario); $I->wantTo('Check that MainPage and About are work'); $I->amOnPage('/'); $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); $I->see(' '); // !       $I->amOnPage('/about'); $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); $I->see(' '); // !       about 

As you know: run early. You will receive a message stating that the test failed. Since He is not quite aware of which site to open the main page. Edit the modules.config.PhpBrowser.url section in the tests/acceptance.suite.yml file. For example, I got there: url: http://rh.dev/


Also in the test code, dubbing immediately catches the eye. It can be refactored by adding a new method to the tests/_support/AcceptanceTester.php class. Either by inheriting from it - create your own and add a method there. But this is another conversation not about tests.


So, click the following commands:


$ cept build - after making changes to the configuration files, rebuilding is always necessary
$ cept run acceptance - we run a test for execution


You should receive the message: OK (1 test, 4 assertion)


Actually - everything! You have created the first test, which for you can check the adequacy of pages throughout the site. Which is especially useful when there are a lot of these pages, and the boss wants to roll faster and faster each time. Not forgetting to hand out scams that something was broken on the site.


In the future, you can also check forms, Ajax, REST, JavaScript via Selenium and various other things.


Creation of the first test: functional or Functional


Immediately important quotation from the documentation: "In case you do not use frameworks, there is almost no point in writing functional tests."
For this kind of test, you need any framework supported by Codeception: Yii1 / 2, ZF, Symfony, etc. This applies only to functional tests.
Unfortunately I could not find a specific link with a list of what is supported.

Functional tests are a bit similar to acceptance tests. But unlike the latter, there is no need to start the web server: we call our framework, with the emulation of request variables (get, post).
Official documentation recommends testing unstable parts of the application using functional tests, and stable using acceptance tests. This is due to the fact that functional tests do not require the use of a web server and, at times, may offer more detailed debugging output.


The first thing we need to start with is to edit the configuration file in tests/functional.suite.yml , indicating in it the module of our framework, instead of the phrase "# add a framework module here". And all the subtleties of customization - will have to read in the official documentation.


I will show the example of non-template Yii2 (if you have the Basic or Advanced template installed, then there is a description and an option at the top of this page): http://codeception.com/for/yii#Manual-Setup--Configuration


See the steps
  1. In the file tests/_bootstrap.php add a constant: defined('YII_ENV') or define('YII_ENV', 'test'); . If there is no file, we create and add to the root codeception.yml settings.bootstrap: _bootstrap.php. Such files will need to be invested in all test folders. If you forget - Codeception will remind you of this.
  2. In the config folder of the yii application, next to main.php put test.php , which we fill out from the manual
  3. Expertly found that the module does not see my vendors and is experiencing problems understanding where it is in the file system. Therefore, I added test.php with a couple more lines:
     require_once(__DIR__ . '/../../../vendor/autoload.php'); require_once(__DIR__ . '/../../../vendor/yiisoft/yii2/Yii.php'); require_once(__DIR__ . '/../../../common/config/bootstrap.php'); // @approot -   . +        $_SERVER['SCRIPT_FILENAME'] = realpath(Yii::getAlias('@approot/web/index.php')); $_SERVER['SCRIPT_NAME'] = '/'.basename($_SERVER['SCRIPT_FILENAME']); 

$ cept generate:cept functional myFirstFunctional - create the first test script
The created tests/functional/myFirstFunctionalCept.php filled in the same way as the previous test file. With one difference in the first line:
$I = new FunctionalTester($scenario);


And further on the material covered above:


$ cept build - after making changes to the configuration files, rebuilding is always necessary
$ cept run functional - run a test for execution


You should receive the message: OK (1 test, 4 assertion)


Creating the first test: unit tests or Unit-Tets


If previous tests looked at your application as a whole: from the entry point to the exit point. These unit tests help to sort everything out, giving the opportunity to test every brick, aka module, application.


What to test and how deep - on Habré quite a lot of articles. In some situations, they will tell you that it is imperative to test all methods and classes completely. In others - the conversation will be a little different. For example, this article caught my eye: The tragedy of one hundred percent code coverage


At my place I will test a class that works on the ActiveRecord pattern: I will load data from an array and start validation. If any required field is later added and, as is usual everywhere, everyone will forget about it: the test will immediately express its objection.


The second stage I will test one of my helpers. The idea is more indicative than useful.


The beginning is already familiar:


tests/unit.suite.yml - we rule according to our framework (if you use it).
$ cept build - after making changes to configuration files, rebuilding is always necessary.
$ cept generate:test unit SmokeUnit - create a dummy for the future test.


Full listing of my test
 <?php namespace tests\unit; use common\helpers\JsonRhHelper; use frontend\modules\wot\models\WotMonitoringClan; class SmokeUnitTest extends \Codeception\Test\Unit { /** * @var \UnitTester */ protected $tester; /** * @var array -       */ protected $clanFixture = [ 'WotMonitoringClan' => [ 'clan_id' => 1, 'status' => '1', 'name' => 'DNO', 'tag' => ' ' ] ]; protected function _before() { } protected function _after() { } /** * ,       */ public function testCheckClanAR() { $clan = new WotMonitoringClan(); $clan->load($this->clanFixture); // -     $this->assertTrue($clan->validate()); //    $fullClanTag = '[' . $clan->tag . ']'; $this->assertTrue($clan->fullClanTag === $fullClanTag); // ,   ,   $clan->clan_id = null; $this->assertFalse($clan->validate()); } /** * ,   JSONa      */ public function testStaticHelper() { //   $expectedArray = ['success' => 'myTest']; $respArray = JsonRhHelper::success('myTest', false); $this->assertTrue($expectedArray === $respArray); //    $expectedArray = [ 'error' => [ 'message' => 'myTest', 'id' => 13255 ] ]; $respArray = JsonRhHelper::error('myTest', 13255, false); $this->assertTrue($expectedArray === $respArray); } } 

$ cept run unit - run a test for execution. We see OK (2 tests, 5 assertions)


I will explain a little:
$this->assertTrue($clan->validate()); - as the name suggests: expects that the variable or the result of the method contains the logical TRUE. Counterweight: $this->assertFalse()
$this->assertEquals(1, count($myArray)); - expects equality of two parameters


Those. a couple of checks you can do some basic things. Spread a straw, so to speak. And at your leisure, read about the rest of the test expressions: http://www.phpunit.de/manual/3.4/en/api.html#api.assert


By the way! Now that we have created all the tests, and our application is ready to start living in a new way. When the tests will be run 1 time before rolling out. I will say what I did not mention at the beginning: after the run parameter, you can omit the type of tests. Then all types of tests will be executed in turn: $ cept run

Finally


Of course in this article everything is simplified and written superficially. But, you know that this topic is not one article. Not to mention the very Best Practices that are either stuffed with their bumps, or you have time to read about them in advance.


So let's try to start in this format and see what comes of it.


If the required audience is found, I will definitely try to talk about the Mock objects I dropped, Fixtures, test databases with dumps and many more interesting things that are used in this direction.



')

Source: https://habr.com/ru/post/329418/


All Articles