Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), prepare some examples of automated tests (API tests) for user-related operations in the tests directory of the API to ensure that the application will not affect existing functions when changing or adding new functions

运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期

Yii2 Advanced in Action Series: RESTful API + RPC Services + Internationalization + Logging & Testing

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), support for creating new API directories, configuration and environment, testing, vagrant, etc.

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), implement model hierarchy: data layer, logic layer, clarify common directory, application, module inheritance, reference relationship

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), implement RESTful web service, support internationalization (drivingly set the target language, default to simplified Chinese)

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), prepare some examples of automated tests (API tests) for user-related operations in the tests directory of the API to ensure that the application will not affect existing functions when changing or adding new functions

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), adjust the default character set to: utf8mb4, the adjustment of the interface response format, the empty array is automatically converted to empty objects, and the request log message is collected in the interface application (1 request corresponds to 1 log message) to the database, and the corresponding interface to implement the log function: log list (set data filter to enable filter processing), log details

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), adjust the default character set to: utf8mb4, the adjustment of the interface response format, the empty array is automatically converted to empty objects, and the request log message is collected in the interface application (1 request corresponds to 1 log message) to the database, and the corresponding interface to implement the log function: log list (set data filter to enable filter processing), log details (2)

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), realize the soft deletion of ActiveRecord, generate ActiveQuery, and customize the query class

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), realize the soft deletion of ActiveRecord, generate ActiveQuery, and customize the query class (2)

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), application/x-www-form-urlencoded and multipart/form-data input formats, default support, new application/json input format support

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new remote procedure call application (implement hprose 2.0 for PHP’s RPC server), support for creating new RPC directories, configuration and environment, testing, Vagrant, etc.

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new remote procedure call application (implement hprose 2.0 for PHP RPC server), implement the corresponding RPC service of the page in the RPC directory, and implement the RPC client in the API directory

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, the implementation of uuid

Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, automatic timing deletion of log messages

1. Delete the controller \API\Controllers\SiteController.php, delete the model \api\models\contactform.php, \api\models\loginform.php, \api\models\PasswordResetRequ estform.php, \api\models\resetpasswordform.php, \api\models\signupform.php, delete the directory (view related) \api\views, \api\assets, \api\web\css 2. Delete the relevant files of the test (unit test, functional test, acceptance test), delete \api\tests\acceptance\homecest.php, delete \API\Tests\Functional\AboutCest.php, \API\Tests\Functional\ContactCest.php, \API\Tests\Functio NAL\HOMECEST.php, \API\Tests\Functional\logincest.php, \api\tests\functional\signupcest.php, delete \API\Tests\Unit\Models\ContactFormTest.php, \API\Tests\Unit\Models\PasswordResetRequestFormTest .php, \api\tests\unit\models\resetpasswordformtest.php, \api\tests\unit\models\signupformtest.php 3. Run all the sample tests, and report an error: Failures! Tests: 24, assertions: 57, failures: 5, as shown in Figure 1
运行所有的样例测试,报错:FAILURES! Tests: 24, Assertions: 57, Failures: 5
Figure 1


Codeception PHP Testing Framework v2.4.1
Powered by PHPUnit 7.0.3 by Sebastian Bergmann and contributors.

Frontend\tests.functional Tests (12) -------------------------------------------------------------------------------------------------------------------------
+ AboutCest: Check about (0.10s)
+ ContactCest: Check contact (0.19s)
x ContactCest: Check contact submit no data (0.04s)
x ContactCest: Check contact submit not correct email (0.02s)
+ ContactCest: Check contact submit correct data (0.08s)
+ HomeCest: Check open (0.01s)
x LoginCest: Check empty (0.02s)
+ LoginCest: Check wrong password (0.03s)
+ LoginCest: Check valid login (0.58s)
x SignupCest: Signup with empty fields (0.02s)
x SignupCest: Signup with wrong email (0.03s)
+ SignupCest: Signup successfully (0.59s)
--------------------------------------------------------------------------------------------------------------------------------------------------------------

Frontend\tests.unit Tests (8) --------------------------------------------------------------------------------------------------------------------------------
+ ContactFormTest: Send email (0.02s)
+ PasswordResetRequestFormTest: Send message with wrong email address (0.03s)
+ PasswordResetRequestFormTest: Not send emails to inactive user (0.03s)
+ PasswordResetRequestFormTest: Send email successfully (0.04s)
+ ResetPasswordFormTest: Reset wrong token (0.03s)
+ ResetPasswordFormTest: Reset correct token (0.59s)
+ SignupFormTest: Correct signup (1.14s)
+ SignupFormTest: Not correct signup (0.03s)
--------------------------------------------------------------------------------------------------------------------------------------------------------------


Time: 4.83 seconds, Memory: 26.00MB

There were 5 failures:

---------
1) ContactCest: Check contact submit no data
 Test  tests\functional\ContactCest.php:checkContactSubmitNoData
 Step  See "Name cannot be blank",".help-block"
 Fail  Failed asserting that any element by '.help-block' on user /index-test.php/site/contact
+ <p class="help-block help-block-error">Name不能为空。</p>
+ <p class="help-block help-block-error">Email不能为空。</p>
+ <p class="help-block help-block-error">Subject不能为空。</p>
+ <p class="help-block help-block-error">Body不能为空。</p>
+ <p class="help-block help-block-error">验证码不正确。</p>
contains text 'Name cannot be blank'

Scenario Steps:

 4. $I->see("Name cannot be blank",".help-block") at tests\_support\FunctionalTester.php:26
 3. $I->see("Contact","h1") at tests\functional\ContactCest.php:23
 2. $I->submitForm("#contact-form",[]) at tests\functional\ContactCest.php:22
 1. $I->amOnuser(["site/contact"]) at tests\functional\ContactCest.php:12


---------
2) ContactCest: Check contact submit not correct email
 Test  tests\functional\ContactCest.php:checkContactSubmitNotCorrectEmail
 Step  See "Email is not a valid email address.",".help-block"
 Fail  Failed asserting that any element by '.help-block' on user /index-test.php/site/contact
+ <p class="help-block help-block-error"></p>
+ <p class="help-block help-block-error">Email不是有效的邮箱地址。</p>
+ <p class="help-block help-block-error"></p>
+ <p class="help-block help-block-error"></p>
+ <p class="help-block help-block-error"></p>
contains text 'Email is not a valid email address.'

Scenario Steps:

 3. $I->see("Email is not a valid email address.",".help-block") at tests\_support\FunctionalTester.php:26
 2. $I->submitForm("#contact-form",{"ContactForm[name]":"tester","ContactForm[email]":"tester.email","ContactForm[subject]":"test subject","ContactForm[b...})
 at tests\functional\ContactCest.php:34
 1. $I->amOnuser(["site/contact"]) at tests\functional\ContactCest.php:12


---------
3) LoginCest: Check empty
 Test  tests\functional\LoginCest.php:checkEmpty
 Step  See "Username cannot be blank.",".help-block"
 Fail  Failed asserting that any element by '.help-block' on user /index-test.php/site/login
+ <p class="help-block help-block-error">Username不能为空。</p>
+ <p class="help-block help-block-error">Password不能为空。</p>
+ <p class="help-block help-block-error"></p>
contains text 'Username cannot be blank.'

Scenario Steps:

 3. $I->see("Username cannot be blank.",".help-block") at tests\_support\FunctionalTester.php:26
 2. $I->submitForm("#login-form",{"LoginForm[username]":"","LoginForm[password]":""}) at tests\functional\LoginCest.php:42
 1. $I->amOnRoute("site/login") at tests\functional\LoginCest.php:29


---------
4) SignupCest: Signup with empty fields
 Test  tests\functional\SignupCest.php:signupWithEmptyFields
 Step  See "Username cannot be blank.",".help-block"
 Fail  Failed asserting that any element by '.help-block' on user /index-test.php/site/signup
+ <p class="help-block help-block-error">Username不能为空。</p>
+ <p class="help-block help-block-error">Email不能为空。</p>
+ <p class="help-block help-block-error">Password不能为空。</p>
contains text 'Username cannot be blank.'

Scenario Steps:

 5. $I->see("Username cannot be blank.",".help-block") at tests\_support\FunctionalTester.php:26
 4. $I->submitForm("#form-signup",[]) at tests\functional\SignupCest.php:21
 3. $I->see("Please fill out the following fields to signup:") at tests\functional\SignupCest.php:20
 2. $I->see("Signup","h1") at tests\functional\SignupCest.php:19
 1. $I->amOnRoute("site/signup") at tests\functional\SignupCest.php:14


---------
5) SignupCest: Signup with wrong email
 Test  tests\functional\SignupCest.php:signupWithWrongEmail
 Step  See "Email is not a valid email address.",".help-block"
 Fail  Failed asserting that any element by '.help-block' on user /index-test.php/site/signup
+ <p class="help-block help-block-error"></p>
+ <p class="help-block help-block-error">Email不是有效的邮箱地址。</p>
+ <p class="help-block help-block-error"></p>
contains text 'Email is not a valid email address.'

Scenario Steps:

 5. $I->see("Email is not a valid email address.",".help-block") at tests\functional\SignupCest.php:39
 4. $I->dontSee("Password cannot be blank.",".help-block") at tests\functional\SignupCest.php:38
 3. $I->dontSee("Username cannot be blank.",".help-block") at tests\functional\SignupCest.php:37
 2. $I->submitForm("#form-signup",{"SignupForm[username]":"tester","SignupForm[email]":"ttttt","SignupForm[password]":"tester_password"}) at tests\functional\
SignupCest.php:32
 1. $I->amOnRoute("site/signup") at tests\functional\SignupCest.php:14


FAILURES!
Tests: 20, Assertions: 48, Failures: 5.




vendor/bin/codecept run


4. The 22nd step of (3) needs to be restored. This step causes the sample test to report an error, and it is adjusted to only support the content negotiation function in the case of a web application. (1) Restore the editing of \common\config\main.php in step 22 (2) Edit \backend\config\main.php, \frontend\config\main.php Note: If no language is detected in the request, use[[languages]] The first configuration item.


    'bootstrap' => ['log', 'contentNegotiator'],
    'components' => [

        'contentNegotiator' => [
            'class' => 'yii\filters\ContentNegotiator',
            'languages' => [
                'en-US',
                'zh-CN',
            ],
        ],

    ],


(3) Edit \api\config\main.php


    'bootstrap' => ['log', 'contentNegotiator'],
    'components' => [

        'contentNegotiator' => [
            'class' => 'yii\filters\ContentNegotiator',
            'formats' => [
                'application/json' => yii\web\Response::FORMAT_JSON,
                'application/xml' => yii\web\Response::FORMAT_XML,
            ],
            'languages' => [
                'en-US',
                'zh-CN',
            ],
        ],

    ],


Delete


        'response' => [
            'format' => yii\web\Response::FORMAT_JSON,
        ],


5. Open Windows PowerShell, execute the init command and select dev as the environment, and then reconfigure the database connection


.\init
0
yes
Yes
Yes
Yes
Yes
Yes


6. Run all the sample tests, which are in line with expectations, as shown in Figure 2
运行所有的样例测试,符合预期
Figure 2


vendor/bin/codecept run


7. To start writing the API test, create the API test suite and run the command, as shown in Figure 3
要开始编写 API 测试,创建 API 测试套件,运行命令
Figure 3


vendor/bin/codecept generate:suite api -c api




Helper \api\tests\Helper\Api was created in E:\wwwroot\github-shuijingwan-yii2-app-advanced\api\tests/_support\Helper\Api.php
Actor ApiTester was created in E:\wwwroot\github-shuijingwan-yii2-app-advanced\api\tests/_support\ApiTester.php
Suite config api.suite.yml was created.

Next steps:
1. Edit api.suite.yml to enable modules for this suite
2. Create first test with generate:cest testName ( or test|cept) command
3. Run tests of this suite with codecept run api command
Suite api generated


8. Edit \api\tests\api.suite.yml to enable the module of the suite


actor: ApiTester
modules:
    enabled:
        - REST:
            url: /v1
            depends: Yii2
        - \api\tests\Helper\Api
    config:
        - Yii2


9. Create a test: get the user list (user/indexempty), as shown in Figure 4
创建测试:获取用户列表(user/IndexEmpty)
Figure 4


vendor/bin/codecept generate:cest api user/IndexEmpty -c api




Test was created in E:\wwwroot\github-shuijingwan-yii2-app-advanced\api\tests\api\user\IndexEmptyCest.php


10,[[yii\base\Application::version|version]], this property specifies the version of the application, the default is1.0, the configuration is: 1.0.0, edit \api\config\main.php, this value should be consistent with the tag on git


    'version' => '1.0.0',


11. Edit \api\tests\_support\help\api.php, add the method of obtaining the current version number (subversion number. revision number)


<?php
namespace api\tests\Helper;

use Yii;
use yii\helpers\StringHelper;

// here you can define custom actions
// all public methods declared in helper class will be available in $I

class Api extends \Codeception\Module
{

    // 获取当前版本号(次版本号.修订号)
    public function getMinorPatch() {
        $version = StringHelper::explode(Yii::$app->version, '.');
        return $version[1] . '.' . $version[2];
    }

}



12. Run the build command, the new function has been added to the Apitester class, as shown in Figure 5
运行 build 命令,新的功能已添加到 ApiTester 类
Figure 5


vendor/bin/codecept build -- -c api


13, \api\tests\_support\_generated\ApitesterActions.php was successfully generated, a new method getMinorPatch(), view, as shown in Figure 6
\api\tests\_support\_generated\ApiTesterActions.php 成功生成,新增方法 getMinorPatch(),查看
Figure 6
14. Install flow/jsonpath to check the structure of the response, as shown in Figure 7
安装 flow/jsonpath ,以检查响应的结构
Figure 7


composer require --prefer-dist flow/jsonpath




Using version ^0.4.0 for flow/jsonpath
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing flow/jsonpath (0.4.0): Downloading (100%)
Writing lock file
Generating autoload files


15. It is necessary to implement a public method for each test, let the indexisJSON obtain the user list through the REST API test (the user list is empty, the JSON response), and let the indexisXML pass the REST API Test get user list (user list is empty, xml response), edit \api\tests\api\user\indexemptycest.php


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;

class IndexEmptyCest
{
    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    // 获取用户列表(用户列表为空、JSON响应)
    public function indexIsJson(ApiTester $I)
    {
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users');
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 20001,
            'message' => Yii::t('error', '20001'),
        ]);
    }

    // 获取用户列表(用户列表为空、XML响应)
    public function indexIsXml(ApiTester $I)
    {
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users');
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20001]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('error', '20001')]));
    }
}



16. Run the test, get the detailed output, and you can see the step by step behavior report, which is in line with expectations, as shown in Figure 8
运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
8


vendor/bin/codecept run --steps -- -c api




Codeception PHP Testing Framework v2.4.1
Powered by PHPUnit 7.1.2 by Sebastian Bergmann and contributors.

Api\tests.api Tests (2) -----------------------------------------------------
IndexEmptyCest: Index is json
Signature: api\tests\user\IndexEmptyCest:indexIsJson
Test: tests\api\user\IndexEmptyCest.php:indexIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send get "/users"
 I see response code is 200
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20001,"message":"User list is empty"}
 PASSED

IndexEmptyCest: Index is xml
Signature: api\tests\user\IndexEmptyCest:indexIsXml
Test: tests\api\user\IndexEmptyCest.php:indexIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send get "/users"
 I see response code is 200
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

-----------------------------------------------------------------------------

Api\tests.functional Tests (0) ----------------------------------------------
-----------------------------------------------------------------------------

Api\tests.unit Tests (0) ----------------------------------------------------
-----------------------------------------------------------------------------


Time: 1.11 seconds, Memory: 16.00MB

OK (2 tests, 12 assertions)


17. Create a test: get the user list (user/index)


vendor/bin/codecept generate:cest api user/Index -c api


18. You need to implement a public method for each test, use fixtures, let the indexisjson get the user list through the REST API test (get the user list success, json response), let the indexisxml pass the REST API Test to get user list (get user list success, xml response), edit \api\tests\api\user\indexcest.php


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;
use api\fixtures\UserFixture;

class IndexCest
{
    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    /**
     * @return array
     */
    public function _fixtures()
    {
        return [
            'user' => [
                'class' => UserFixture::className(),
                'dataFile' => codecept_data_dir() . 'user.php'
            ]
        ];
    }

    // 获取用户列表(获取用户列表成功、JSON响应)
    public function indexIsJson(ApiTester $I)
    {
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users');
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        $I->seeResponseJsonMatchesJsonPath('$.data');
        $I->seeResponseJsonMatchesJsonPath('$.data.items');
        $I->seeResponseJsonMatchesJsonPath('$.data._links');
        $I->seeResponseJsonMatchesJsonPath('$.data._meta');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 10000,
            'message' => Yii::t('success', '10001'),
        ]);
    }

    // 获取用户列表(获取用户列表成功、XML响应)
    public function indexIsXml(ApiTester $I)
    {
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users');
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        $I->seeXmlResponseMatchesXpath('//data');
        $I->seeXmlResponseMatchesXpath('//data/items');
        $I->seeXmlResponseMatchesXpath('//data/_links');
        $I->seeXmlResponseMatchesXpath('//data/_meta');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 10000]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('success', '10001')]));
    }
}



19. Run the test, get detailed output, you can see step by step behavior report, in line with expectations


vendor/bin/codecept run --steps -- -c api




IndexCest: Index is json
Signature: api\tests\user\IndexCest:indexIsJson
Test: tests\api\user\IndexCest.php:indexIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send get "/users"
 I see response code is 200
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response json matches json path "$.data"
 I see response json matches json path "$.data.items"
 I see response json matches json path "$.data._links"
 I see response json matches json path "$.data._meta"
 I see response contains json {"code":10000,"message":"Get user list success"}
 PASSED

IndexCest: Index is xml
Signature: api\tests\user\IndexCest:indexIsXml
Test: tests\api\user\IndexCest.php:indexIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send get "/users"
 I see response code is 200
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response matches xpath "//data"
 I see xml response matches xpath "//data/items"
 I see xml response matches xpath "//data/_links"
 I see xml response matches xpath "//data/_meta"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED


20, get /users/{id}: return the details of the user {id}, create a test: get user details


vendor/bin/codecept generate:cest api user/View -c api


21. Edit \api\tests\api\user\viewcest.php to get user details (user ID: {id}, does not exist/user id: {id}, the status is deleted/obtained user details successfully)


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;
use api\fixtures\UserFixture;

class ViewCest
{
    const STATUS_DELETED = 0; //状态:已删除
    const STATUS_ACTIVE = 10; //状态:活跃

    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    /**
     * @return array
     */
    public function _fixtures()
    {
        return [
            'user' => [
                'class' => UserFixture::className(),
                'dataFile' => codecept_data_dir() . 'user.php'
            ]
        ];
    }

    // 获取用户详情(获取用户详情成功、JSON响应)
    public function viewIsJson(ApiTester $I)
    {
        $id = 1;
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        $I->seeResponseJsonMatchesJsonPath('$.data');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 10000,
            'message' => Yii::t('success', '10002'),
        ]);
    }

    // 获取用户详情(获取用户详情成功、XML响应)
    public function viewIsXml(ApiTester $I)
    {
        $id = 1;
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        $I->seeXmlResponseMatchesXpath('//data');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 10000]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('success', '10002')]));
    }

    // 获取用户详情,使用不存在的ID(用户ID:{id},不存在、JSON响应)
    public function viewWithNotExistIdIsJson(ApiTester $I)
    {
        $id = 9999;
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::NOT_FOUND); // 404
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 20002,
            'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20002'), ['id' => $id])),
        ]);
    }

    // 获取用户详情,使用不存在的ID(用户ID:{id},不存在、XML响应)
    public function viewWithNotExistIdIsXml(ApiTester $I)
    {
        $id = 9999;
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::NOT_FOUND); // 404
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20002]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('error', Yii::t('error', Yii::t('error', '20002'), ['id' => $id]))]));
    }

    // 获取用户详情(用户ID:{id},的状态为已删除、JSON响应)
    public function viewStatusDeletedIsJson(ApiTester $I)
    {
        $id = 2;
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 20003,
            'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20003'), ['id' => $id])),
        ]);
    }

    // 获取用户详情(用户ID:{id},的状态为已删除、XML响应)
    public function viewStatusDeletedIsXml(ApiTester $I)
    {
        $id = 2;
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendGET('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20003]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('error', Yii::t('error', Yii::t('error', '20003'), ['id' => $id]))]));
    }
}



22. Run the test, obtain detailed output, and you can see the step by step behavior report, which is in line with expectations


vendor/bin/codecept run --steps -- -c api




ViewCest: View is json
Signature: api\tests\user\ViewCest:viewIsJson
Test: tests\api\user\ViewCest.php:viewIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send get "/users/1"
 I see response code is 200
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response json matches json path "$.data"
 I see response contains json {"code":10000,"message":"Get user details success"}
 PASSED

ViewCest: View is xml
Signature: api\tests\user\ViewCest:viewIsXml
Test: tests\api\user\ViewCest.php:viewIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send get "/users/1"
 I see response code is 200
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response matches xpath "//data"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

ViewCest: View with not exist id is json
Signature: api\tests\user\ViewCest:viewWithNotExistIdIsJson
Test: tests\api\user\ViewCest.php:viewWithNotExistIdIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send get "/users/9999"
 I see response code is 404
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20002,"message":"User ID: 9999, does not exist"}
 PASSED

ViewCest: View with not exist id is xml
Signature: api\tests\user\ViewCest:viewWithNotExistIdIsXml
Test: tests\api\user\ViewCest.php:viewWithNotExistIdIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send get "/users/9999"
 I see response code is 404
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

ViewCest: View status deleted is json
Signature: api\tests\user\ViewCest:viewStatusDeletedIsJson
Test: tests\api\user\ViewCest.php:viewStatusDeletedIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send get "/users/2"
 I see response code is 200
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20003,"message":"User ID: 2, status is deleted"}
 PASSED

ViewCest: View status deleted is xml
Signature: api\tests\user\ViewCest:viewStatusDeletedIsXml
Test: tests\api\user\ViewCest.php:viewStatusDeletedIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send get "/users/2"
 I see response code is 200
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED


23. POST /users: Create a new user, create a test: create a user


vendor/bin/codecept generate:cest api user/Create -c api


24. Edit \API\Tests\API\User\CreateCest.php, support (creation user success, data validation failed: {firsErrors})


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;
use api\fixtures\UserFixture;

class CreateCest
{
    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    /**
     * @return array
     */
    public function _fixtures()
    {
        return [
            'user' => [
                'class' => UserFixture::className(),
                'dataFile' => codecept_data_dir() . 'user.php'
            ]
        ];
    }

    // 创建用户(创建用户成功、JSON响应)
    public function createIsJson(ApiTester $I)
    {
        $data = [
            'username' => '111111',
            'email' => '111111@163.com',
            'password' => '111111',
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::CREATED); // 201
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        $I->seeResponseJsonMatchesJsonPath('$.data');
        $I->seeResponseJsonMatchesJsonPath('$.data.username');
        $I->seeResponseJsonMatchesJsonPath('$.data.email');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 10000,
            'message' => Yii::t('success', '10003'),
            'data' => [
                'username' => $data['username'],
                'email' => $data['email'],
            ],
        ]);
    }

    // 创建用户(创建用户成功、XML响应)
    public function createIsXml(ApiTester $I)
    {
        $data = [
            'username' => '111111',
            'email' => '111111@163.com',
            'password' => '111111',
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::CREATED); // 201
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        $I->seeXmlResponseMatchesXpath('//data');
        $I->seeXmlResponseMatchesXpath('//data//username');
        $I->seeXmlResponseMatchesXpath('//data//email');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 10000]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('success', '10003')]));
        $I->seeXmlResponseIncludes(Xml::toXml(['username' => $data['username']]));
        $I->seeXmlResponseIncludes(Xml::toXml(['email' => $data['email']]));
    }

    // 创建用户,使用空的字段值(数据验证失败:{firstErrors}、JSON响应)
    public function createWithEmptyFieldsIsJson(ApiTester $I)
    {
        $data = [];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Username cannot be blank.']);
    }

    // 创建用户,使用空的字段值(数据验证失败:{firstErrors}、XML响应)
    public function createWithEmptyFieldsIsXml(ApiTester $I)
    {
        $data = [];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Username cannot be blank.']));
    }

    // 创建用户,使用错误的邮箱(数据验证失败:{firstErrors}、JSON响应)
    public function createWithWrongEmailIsJson(ApiTester $I)
    {
        $data = [
            'username' => '111111',
            'email' => '111111',
            'password' => '111111',
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Email is not a valid email address.']);
    }

    // 创建用户,使用错误的邮箱(数据验证失败:{firstErrors}、XML响应)
    public function createWithWrongEmailIsXml(ApiTester $I)
    {
        $data = [
            'username' => '111111',
            'email' => '111111',
            'password' => '111111',
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Email is not a valid email address.']));
    }

    // 创建用户,使用已经存在的字段值(数据验证失败:{firstErrors}、JSON响应)
    public function createWithExistFieldsIsJson(ApiTester $I)
    {
        $data = [
            'username' => 'troy.becker',
            'email' => 'nicolas.dianna@hotmail.com',
            'password' => 'some_password',
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Username "troy.becker" has already been taken.']);
    }

    // 创建用户,使用已经存在的字段值(数据验证失败:{firstErrors}、XML响应)
    public function createWithExistFieldsIsXml(ApiTester $I)
    {
        $data = [
            'username' => 'troy.becker',
            'email' => 'nicolas.dianna@hotmail.com',
            'password' => 'some_password',
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPOST('/users', $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Username "troy.becker" has already been taken.']));
    }
}



25. Run the test, get detailed output, you can see step by step behavior report, which is in line with expectations


vendor/bin/codecept run --steps -- -c api




CreateCest: Create is json
Signature: api\tests\user\CreateCest:createIsJson
Test: tests\api\user\CreateCest.php:createIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send post "/users",{"username":"111111","email":"111111@163.com","password":"111111"}
 I see response code is 201
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response json matches json path "$.data"
 I see response json matches json path "$.data.username"
 I see response json matches json path "$.data.email"
 I see response contains json {"code":10000,"message":"Create user success","data":{"username":"111111","email":"111...}
 PASSED

CreateCest: Create is xml
Signature: api\tests\user\CreateCest:createIsXml
Test: tests\api\user\CreateCest.php:createIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send post "/users",{"username":"111111","email":"111111@163.com","password":"111111"}
 I see response code is 201
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response matches xpath "//data"
 I see xml response matches xpath "//data//username"
 I see xml response matches xpath "//data//email"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

CreateCest: Create with empty fields is json
Signature: api\tests\user\CreateCest:createWithEmptyFieldsIsJson
Test: tests\api\user\CreateCest.php:createWithEmptyFieldsIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send post "/users",[]
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Username cannot be blank."}
 PASSED

CreateCest: Create with empty fields is xml
Signature: api\tests\user\CreateCest:createWithEmptyFieldsIsXml
Test: tests\api\user\CreateCest.php:createWithEmptyFieldsIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send post "/users",[]
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

CreateCest: Create with wrong email is json
Signature: api\tests\user\CreateCest:createWithWrongEmailIsJson
Test: tests\api\user\CreateCest.php:createWithWrongEmailIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send post "/users",{"username":"111111","email":"111111","password":"111111"}
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Email is not a valid email address."}
 PASSED

CreateCest: Create with wrong email is xml
Signature: api\tests\user\CreateCest:createWithWrongEmailIsXml
Test: tests\api\user\CreateCest.php:createWithWrongEmailIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send post "/users",{"username":"111111","email":"111111","password":"111111"}
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

CreateCest: Create with exist fields is json
Signature: api\tests\user\CreateCest:createWithExistFieldsIsJson
Test: tests\api\user\CreateCest.php:createWithExistFieldsIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send post "/users",{"username":"troy.becker","email":"nicolas.dianna@hotmail.com","password":"some_password"}
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Username "troy.becker" has already been taken."}
 PASSED

CreateCest: Create with exist fields is xml
Signature: api\tests\user\CreateCest:createWithExistFieldsIsXml
Test: tests\api\user\CreateCest.php:createWithExistFieldsIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send post "/users",{"username":"troy.becker","email":"nicolas.dianna@hotmail.com","password":"some_password"}
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED


26, put /users/{id}: update a user, copy \api\tests\api\user\createcest.php to \API\Tests\API\User\UpdateCest.php, update user (user ID: {id}, does not exist/data authentication failed: {firsErrors}/update user success), edit


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;
use api\fixtures\UserFixture;

class UpdateCest
{
    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    /**
     * @return array
     */
    public function _fixtures()
    {
        return [
            'user' => [
                'class' => UserFixture::className(),
                'dataFile' => codecept_data_dir() . 'user.php'
            ]
        ];
    }

    // 更新用户(更新用户成功、JSON响应)
    public function updateIsJson(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => '111111@163.com',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        $I->seeResponseJsonMatchesJsonPath('$.data');
        $I->seeResponseJsonMatchesJsonPath('$.data.email');
        $I->seeResponseJsonMatchesJsonPath('$.data.status');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 10000,
            'message' => Yii::t('success', '10004'),
            'data' => [
                'email' => $data['email'],
                'status' => $data['status'],
            ],
        ]);
    }

    // 更新用户(更新用户成功、XML响应)
    public function updateIsXml(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => '111111@163.com',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        $I->seeXmlResponseMatchesXpath('//data');
        $I->seeXmlResponseMatchesXpath('//data//email');
        $I->seeXmlResponseMatchesXpath('//data//status');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 10000]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('success', '10004')]));
        $I->seeXmlResponseIncludes(Xml::toXml(['email' => $data['email']]));
        $I->seeXmlResponseIncludes(Xml::toXml(['status' => $data['status']]));
    }

    // 更新用户,使用不存在的ID(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithNotExistIdIsJson(ApiTester $I)
    {
        $id = 9999;
        $data = [
            'email' => '111111@163.com',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::NOT_FOUND); // 404
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20002]);
        $I->seeResponseContainsJson(['message' => 'User ID: 9999, does not exist']);
    }

    // 更新用户,使用不存在的ID(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithNotExistIdIsXml(ApiTester $I)
    {
        $id = 9999;
        $data = [
            'email' => '111111@163.com',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::NOT_FOUND); // 404
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20002]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'User ID: 9999, does not exist']));
    }

    // 更新用户,使用空的字段值(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithEmptyFieldsIsJson(ApiTester $I)
    {
        $id = 1;
        $data = [];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Email cannot be blank.']);
    }

    // 更新用户,使用空的字段值(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithEmptyFieldsIsXml(ApiTester $I)
    {
        $id = 1;
        $data = [];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Email cannot be blank.']));
    }

    // 更新用户,使用错误的邮箱(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithWrongEmailIsJson(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => '111111',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Email is not a valid email address.']);
    }

    // 更新用户,使用错误的邮箱(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithWrongEmailIsXml(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => '111111',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Email is not a valid email address.']));
    }

    // 更新用户,使用已经存在的字段值(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithExistFieldsIsJson(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => 'nicolas.dianna@hotmail.com',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Email "nicolas.dianna@hotmail.com" has already been taken.']);
    }

    // 更新用户,使用已经存在的字段值(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithExistFieldsIsXml(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => 'nicolas.dianna@hotmail.com',
            'password' => '111111',
            'status' => 0,
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Email "nicolas.dianna@hotmail.com" has already been taken.']));
    }

    // 更新用户,使用超出范围的状态值(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithNotRangeStatusIsJson(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => '111111@163.com',
            'password' => '111111',
            'status' => 5,
        ];
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson(['code' => 20004]);
        $I->seeResponseContainsJson(['message' => 'Data validation failed: Status is invalid.']);
    }

    // 更新用户,使用超出范围的状态值(数据验证失败:{firstErrors}、JSON响应)
    public function updateWithNotRangeStatusIsXml(ApiTester $I)
    {
        $id = 1;
        $data = [
            'email' => '111111@163.com',
            'password' => '111111',
            'status' => 5,
        ];
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendPUT('/users/' . $id, $data);
        $I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY); // 422
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20004]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => 'Data validation failed: Status is invalid.']));
    }

}



27. Run the test, obtain detailed output, and you can see the step by step behavior report, which is in line with expectations


vendor/bin/codecept run --steps -- -c api




UpdateCest: Update is json
Signature: api\tests\user\UpdateCest:updateIsJson
Test: tests\api\user\UpdateCest.php:updateIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send put "/users/1",{"email":"111111@163.com","password":"111111","status":0}
 I see response code is 200
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response json matches json path "$.data"
 I see response json matches json path "$.data.email"
 I see response json matches json path "$.data.status"
 I see response contains json {"code":10000,"message":"Update user success","data":{"email":"111111@163.com","status...}
 PASSED

UpdateCest: Update is xml
Signature: api\tests\user\UpdateCest:updateIsXml
Test: tests\api\user\UpdateCest.php:updateIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send put "/users/1",{"email":"111111@163.com","password":"111111","status":0}
 I see response code is 200
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response matches xpath "//data"
 I see xml response matches xpath "//data//email"
 I see xml response matches xpath "//data//status"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

UpdateCest: Update with not exist id is json
Signature: api\tests\user\UpdateCest:updateWithNotExistIdIsJson
Test: tests\api\user\UpdateCest.php:updateWithNotExistIdIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send put "/users/9999",{"email":"111111@163.com","password":"111111","status":0}
 I see response code is 404
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20002}
 I see response contains json {"message":"User ID: 9999, does not exist"}
 PASSED

UpdateCest: Update with not exist id is xml
Signature: api\tests\user\UpdateCest:updateWithNotExistIdIsXml
Test: tests\api\user\UpdateCest.php:updateWithNotExistIdIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send put "/users/9999",{"email":"111111@163.com","password":"111111","status":0}
 I see response code is 404
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

UpdateCest: Update with empty fields is json
Signature: api\tests\user\UpdateCest:updateWithEmptyFieldsIsJson
Test: tests\api\user\UpdateCest.php:updateWithEmptyFieldsIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send put "/users/1",[]
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Email cannot be blank."}
 PASSED

UpdateCest: Update with empty fields is xml
Signature: api\tests\user\UpdateCest:updateWithEmptyFieldsIsXml
Test: tests\api\user\UpdateCest.php:updateWithEmptyFieldsIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send put "/users/1",[]
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

UpdateCest: Update with wrong email is json
Signature: api\tests\user\UpdateCest:updateWithWrongEmailIsJson
Test: tests\api\user\UpdateCest.php:updateWithWrongEmailIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send put "/users/1",{"email":"111111","password":"111111","status":0}
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Email is not a valid email address."}
 PASSED

UpdateCest: Update with wrong email is xml
Signature: api\tests\user\UpdateCest:updateWithWrongEmailIsXml
Test: tests\api\user\UpdateCest.php:updateWithWrongEmailIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send put "/users/1",{"email":"111111","password":"111111","status":0}
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

UpdateCest: Update with exist fields is json
Signature: api\tests\user\UpdateCest:updateWithExistFieldsIsJson
Test: tests\api\user\UpdateCest.php:updateWithExistFieldsIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send put "/users/1",{"email":"nicolas.dianna@hotmail.com","password":"111111","status":0}
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Email "nicolas.dianna@hotmail.com" has already bee...}
 PASSED

UpdateCest: Update with exist fields is xml
Signature: api\tests\user\UpdateCest:updateWithExistFieldsIsXml
Test: tests\api\user\UpdateCest.php:updateWithExistFieldsIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send put "/users/1",{"email":"nicolas.dianna@hotmail.com","password":"111111","status":0}
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

UpdateCest: Update with not range status is json
Signature: api\tests\user\UpdateCest:updateWithNotRangeStatusIsJson
Test: tests\api\user\UpdateCest.php:updateWithNotRangeStatusIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send put "/users/1",{"email":"111111@163.com","password":"111111","status":5}
 I see response code is 422
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20004}
 I see response contains json {"message":"Data validation failed: Status is invalid."}
 PASSED

UpdateCest: Update with not range status is xml
Signature: api\tests\user\UpdateCest:updateWithNotRangeStatusIsXml
Test: tests\api\user\UpdateCest.php:updateWithNotRangeStatusIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send put "/users/1",{"email":"111111@163.com","password":"111111","status":5}
 I see response code is 422
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED


28, delete /users/{id}: delete the user, copy \api\tests\api\user\viewcest.php as \API\Tests\API\User\DeleteCest.php, delete user (user ID: {id}, no user exists/delete user success), edit


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;
use api\fixtures\UserFixture;

class DeleteCest
{
    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    /**
     * @return array
     */
    public function _fixtures()
    {
        return [
            'user' => [
                'class' => UserFixture::className(),
                'dataFile' => codecept_data_dir() . 'user.php'
            ]
        ];
    }

    // 删除用户(删除用户成功、JSON响应)
    public function deleteIsJson(ApiTester $I)
    {
        $id = 1;
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendDELETE('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 10000,
            'message' => Yii::t('success', '10005'),
        ]);
    }

    // 删除用户(删除用户成功、XML响应)
    public function deleteIsXml(ApiTester $I)
    {
        $id = 1;
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendDELETE('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 10000]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('success', '10005')]));
    }

    // 获取用户详情,使用不存在的ID(用户ID:{id},不存在、JSON响应)
    public function deleteWithNotExistIdIsJson(ApiTester $I)
    {
        $id = 9999;
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendDELETE('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::NOT_FOUND); // 404
        $I->seeResponseIsJson();
        // 检查响应的结构
        $I->seeResponseJsonMatchesJsonPath('$.code');
        $I->seeResponseJsonMatchesJsonPath('$.message');
        // 检查响应的数据
        $I->seeResponseContainsJson([
            'code' => 20002,
            'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20002'), ['id' => $id])),
        ]);
    }

    // 获取用户详情,使用不存在的ID(用户ID:{id},不存在、XML响应)
    public function deleteWithNotExistIdIsXml(ApiTester $I)
    {
        $id = 9999;
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendDELETE('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::NOT_FOUND); // 404
        $I->seeResponseIsXml();
        // 检查响应的结构
        $I->seeXmlResponseMatchesXpath('//code');
        $I->seeXmlResponseMatchesXpath('//message');
        // 检查响应的数据
        $I->seeXmlResponseIncludes(Xml::toXml(['code' => 20002]));
        $I->seeXmlResponseIncludes(Xml::toXml(['message' => Yii::t('error', Yii::t('error', Yii::t('error', '20002'), ['id' => $id]))]));
    }
}



29. Run the test, only test the API user/createcest.php, get the detailed output, you can see the step by step behavior report, which is in line with expectations, as shown in Figure 9
运行测试,仅测试 api user/CreateCest.php,获取详细的输出,可看到一步一步的行为报告,符合预期
Figure 9


vendor/bin/codecept run --steps -- -c api api user/DeleteCest.php




Codeception PHP Testing Framework v2.4.1
Powered by PHPUnit 7.1.2 by Sebastian Bergmann and contributors.

Api\tests.api Tests (4) ------------------------------------------------------------------------------------------------
DeleteCest: Delete is json
Signature: api\tests\user\DeleteCest:deleteIsJson
Test: tests\api\user\DeleteCest.php:deleteIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send delete "/users/1"
 I see response code is 200
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":10000,"message":"Delete user success"}
 PASSED

DeleteCest: Delete is xml
Signature: api\tests\user\DeleteCest:deleteIsXml
Test: tests\api\user\DeleteCest.php:deleteIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send delete "/users/1"
 I see response code is 200
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

DeleteCest: Delete with not exist id is json
Signature: api\tests\user\DeleteCest:deleteWithNotExistIdIsJson
Test: tests\api\user\DeleteCest.php:deleteWithNotExistIdIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send delete "/users/9999"
 I see response code is 404
 I see response is json
 I see response json matches json path "$.code"
 I see response json matches json path "$.message"
 I see response contains json {"code":20002,"message":"User ID: 9999, does not exist"}
 PASSED

DeleteCest: Delete with not exist id is xml
Signature: api\tests\user\DeleteCest:deleteWithNotExistIdIsXml
Test: tests\api\user\DeleteCest.php:deleteWithNotExistIdIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send delete "/users/9999"
 I see response code is 404
 I see response is xml
 I see xml response matches xpath "//code"
 I see xml response matches xpath "//message"
 I see xml response includes "DOMDocument"
 I see xml response includes "DOMDocument"
 PASSED

------------------------------------------------------------------------------------------------------------------------


Time: 1.25 seconds, Memory: 16.00MB

OK (4 tests, 24 assertions)


30. Options /Users: Display verbs about end /users support; options /users/{id}: Display verbs about end /users/{id} support, copy \api\tests\api\user\indexcest.php is \api\tests\api\user\optionscest.php, edit


<?php
namespace api\tests\user;

use Yii;
use api\tests\ApiTester;
use Codeception\Util\HttpCode;
use Codeception\Util\Xml;
use api\fixtures\UserFixture;

class OptionsCest
{
    public function _before(ApiTester $I)
    {
    }

    public function _after(ApiTester $I)
    {
    }

    /**
     * @return array
     */
    public function _fixtures()
    {
        return [
            'user' => [
                'class' => UserFixture::className(),
                'dataFile' => codecept_data_dir() . 'user.php'
            ]
        ];
    }

    // 显示关于末端 /users 支持的动词(JSON响应)
    public function optionsIsJson(ApiTester $I)
    {
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendOPTIONS('/users');
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        // 检查响应的数据
        $I->seeHttpHeader('Allow', 'GET, POST, HEAD, OPTIONS');
        $I->seeResponseEquals('');
    }

    // 显示关于末端 /users 支持的动词(XML响应)
    public function optionsIsXml(ApiTester $I)
    {
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendOPTIONS('/users');
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        // 检查响应的数据
        $I->seeHttpHeader('Allow', 'GET, POST, HEAD, OPTIONS');
        $I->seeResponseEquals('');
    }

    // 显示关于末端 /users/{id} 支持的动词(JSON响应)
    public function optionsIdIsJson(ApiTester $I)
    {
        $id = 1;
        $I->haveHttpHeader('Accept', 'application/json; version=' . $I->getMinorPatch() . '');
        $I->sendOPTIONS('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        // 检查响应的数据
        $I->seeHttpHeader('Allow', 'GET, PUT, PATCH, DELETE, HEAD, OPTIONS');
        $I->seeResponseEquals('');
    }

    // 显示关于末端 /users/{id} 支持的动词(XML响应)
    public function optionsIdIsXml(ApiTester $I)
    {
        $id = 1;
        $I->haveHttpHeader('Accept', 'application/xml; version=' . $I->getMinorPatch() . '');
        $I->sendOPTIONS('/users/' . $id);
        $I->seeResponseCodeIs(HttpCode::OK); // 200
        // 检查响应的数据
        $I->seeHttpHeader('Allow', 'GET, PUT, PATCH, DELETE, HEAD, OPTIONS');
        $I->seeResponseEquals('');
    }
}



31. Run the test, only test the API user/optionscest.php, get the detailed output, and you can see the behavior report step by step, which is in line with expectations


vendor/bin/codecept run --steps -- -c api api user/OptionsCest.php




Codeception PHP Testing Framework v2.4.1
Powered by PHPUnit 7.1.2 by Sebastian Bergmann and contributors.

Api\tests.api Tests (4) ------------------------------------------------------------------------------------------------
OptionsCest: Options is json
Signature: api\tests\user\OptionsCest:optionsIsJson
Test: tests\api\user\OptionsCest.php:optionsIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send options "/users"
 I see response code is 200
 I see http header "Allow","GET, POST, HEAD, OPTIONS"
 I see response equals ""
 PASSED

OptionsCest: Options is xml
Signature: api\tests\user\OptionsCest:optionsIsXml
Test: tests\api\user\OptionsCest.php:optionsIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send options "/users"
 I see response code is 200
 I see http header "Allow","GET, POST, HEAD, OPTIONS"
 I see response equals ""
 PASSED

OptionsCest: Options id is json
Signature: api\tests\user\OptionsCest:optionsIdIsJson
Test: tests\api\user\OptionsCest.php:optionsIdIsJson
Scenario --
 I get minor patch
 I have http header "Accept","application/json; version=0.0"
 I send options "/users/1"
 I see response code is 200
 I see http header "Allow","GET, PUT, PATCH, DELETE, HEAD, OPTIONS"
 I see response equals ""
 PASSED

OptionsCest: Options id is xml
Signature: api\tests\user\OptionsCest:optionsIdIsXml
Test: tests\api\user\OptionsCest.php:optionsIdIsXml
Scenario --
 I get minor patch
 I have http header "Accept","application/xml; version=0.0"
 I send options "/users/1"
 I see response code is 200
 I see http header "Allow","GET, PUT, PATCH, DELETE, HEAD, OPTIONS"
 I see response equals ""
 PASSED

------------------------------------------------------------------------------------------------------------------------


Time: 1.19 seconds, Memory: 14.00MB

OK (4 tests, 12 assertions)


32. Run all the sample tests, which are in line with expectations, as shown in Figure 10
运行所有的样例测试,符合预期
Figure 10


vendor/bin/codecept run


Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), implement RESTful web service, support internationalization (drivingly set the target language, default to simplified Chinese) Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), adjust the default character set to: utf8mb4, the adjustment of the interface response format, the empty array is automatically converted to empty objects, and the request log message is collected in the interface application (1 request corresponds to 1 log message) to the database, and the corresponding interface to implement the log function: log list (set data filter to enable filter processing), log details

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.