基于 yiisoft/yii2-app-advanced,在 GitHub 上新建仓库 yii2-app-advanced,新建接口应用(实现 RESTful 风格的 Web Service 服务的 API),在 api 的 tests 目录中准备用户相关操作的一些自动化测试的样例(API 测试),确保应用程序在改变或增加新的功能时不会影响现有的功能 (四)
1、删除控制器 \api\controllers\SiteController.php,删除模型 \api\models\ContactForm.php、\api\models\LoginForm.php、\api\models\PasswordResetRequestForm.php、\api\models\ResetPasswordForm.php、\api\models\SignupForm.php,删除目录(视图相关) \api\views、\api\assets、\api\web\css
2、删除测试(单元测试、功能测试、验收测试)的相关文件,删除 \api\tests\acceptance\HomeCest.php,删除 \api\tests\functional\AboutCest.php、\api\tests\functional\ContactCest.php、\api\tests\functional\HomeCest.php、\api\tests\functional\LoginCest.php、\api\tests\functional\SignupCest.php,删除 \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、运行所有的样例测试,报错:FAILURES! Tests: 24, Assertions: 57, Failures: 5,如图1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 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. |
1 | vendor/bin/codecept run |
4、(三) 的第22步骤需要还原,此步骤导致样例测试报错,调整为仅web应用情况下,才支持内容协商功能
(1)还原 \common\config\main.php 在第22步骤所做的编辑
(2)编辑 \backend\config\main.php、\frontend\config\main.php
注:如果请求中没有检测到语言, 使用 [[languages]] 第一个配置项。
1 2 3 4 5 6 7 8 9 10 11 12 | 'bootstrap' => [ 'log' , 'contentNegotiator' ], 'components' => [ 'contentNegotiator' => [ 'class' => 'yii\filters\ContentNegotiator' , 'languages' => [ 'en-US' , 'zh-CN' , ], ], ], |
(3)编辑 \api\config\main.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | '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' , ], ], ], |
删除
1 2 3 | 'response' => [ 'format' => yii\web\Response::FORMAT_JSON, ], |
5、打开 Windows PowerShell,执行 init 命令并选择 dev 作为环境,然后重新配置数据库连接
1 2 3 4 5 6 7 8 | .\init 0 yes Yes Yes Yes Yes Yes |
6、运行所有的样例测试,符合预期,如图2
1 | vendor/bin/codecept run |
7、要开始编写 API 测试,创建 API 测试套件,运行命令,如图3
1 | vendor/bin/codecept generate:suite api -c api |
1 2 3 4 5 6 7 8 9 | 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、编辑 \api\tests\api.suite.yml 以启用该套件的模块
1 2 3 4 5 6 7 8 9 | actor: ApiTester modules: enabled: - REST: url: /v1 depends: Yii2 - \api\tests\Helper\Api config: - Yii2 |
9、创建测试:获取用户列表(user/IndexEmpty),如图4
1 | vendor/bin/codecept generate:cest api user/IndexEmpty -c api |
1 | Test was created in E:\wwwroot\github-shuijingwan-yii2-app-advanced\api\tests\api\user\IndexEmptyCest.php |
10、[[yii\base\Application::version|version]],该属性指定应用的版本,默认为’1.0’, 配置为:1.0.0,编辑 \api\config\main.php,此值应与 Git 上的 tag 保持一致
1 | 'version' => '1.0.0' , |
11、编辑 \api\tests\_support\Helper\Api.php,添加 获取当前版本号(次版本号.修订号) 的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?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、运行 build 命令,新的功能已添加到 ApiTester 类,如图5
1 | vendor/bin/codecept build -- -c api |
13、\api\tests\_support\_generated\ApiTesterActions.php 成功生成,新增方法 getMinorPatch(),查看,如图6
14、安装 flow/jsonpath ,以检查响应的结构,如图7
1 | composer require --prefer-dist flow/jsonpath |
1 2 3 4 5 6 7 8 | 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、需要为每个测试实现一个公共方法,让 indexIsJson 通过 REST API 测试获取用户列表(用户列表为空、JSON响应),让 indexIsXml 通过 REST API 测试获取用户列表(用户列表为空、XML响应),编辑 \api\tests\api\user\IndexEmptyCest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期,如图8
1 | vendor/bin/codecept run --steps -- -c api |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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、创建测试:获取用户列表(user/Index)
1 | vendor/bin/codecept generate:cest api user/Index -c api |
18、需要为每个测试实现一个公共方法,使用 Fixtures,让 indexIsJson 通过 REST API 测试获取用户列表(获取用户列表成功、JSON响应),让 indexIsXml 通过 REST API 测试获取用户列表(获取用户列表成功、XML响应),编辑 \api\tests\api\user\IndexCest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | <?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
1 | vendor/bin/codecept run --steps -- -c api |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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}: 返回用户 {id} 的详细信息,创建测试:获取用户详情
1 | vendor/bin/codecept generate:cest api user/View -c api |
21、编辑 \api\tests\api\user\ViewCest.php,获取用户详情(用户ID:{id},不存在/用户ID:{id},的状态为已删除/获取用户详情成功)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | <?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
1 | vendor/bin/codecept run --steps -- -c api |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 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: 创建一个新用户,创建测试:创建用户
1 | vendor/bin/codecept generate:cest api user/Create -c api |
24、编辑 \api\tests\api\user\CreateCest.php,支持(创建用户成功、数据验证失败:{firstErrors})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | <?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
1 | vendor/bin/codecept run --steps -- -c api |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 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}: 更新一个用户,复制 \api\tests\api\user\CreateCest.php 为 \api\tests\api\user\UpdateCest.php,更新用户(用户ID:{id},不存在/数据验证失败:{firstErrors}/更新用户成功),编辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | <?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
1 | vendor/bin/codecept run --steps -- -c api |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | 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}: 删除用户,复制 \api\tests\api\user\ViewCest.php 为 \api\tests\api\user\DeleteCest.php,删除用户(用户ID:{id},不存在/删除用户成功),编辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | <?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、运行测试,仅测试 api user/CreateCest.php,获取详细的输出,可看到一步一步的行为报告,符合预期,如图9
1 | vendor/bin/codecept run --steps -- -c api api user/DeleteCest.php |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 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: 显示关于末端 /users 支持的动词;OPTIONS /users/{id}: 显示关于末端 /users/{id} 支持的动词,复制 \api\tests\api\user\IndexCest.php 为 \api\tests\api\user\OptionsCest.php,编辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | <?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、运行测试,仅测试 api user/OptionsCest.php,获取详细的输出,可看到一步一步的行为报告,符合预期
1 | vendor/bin/codecept run --steps -- -c api api user/OptionsCest.php |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 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、运行所有的样例测试,符合预期,如图10
1 | vendor/bin/codecept run |
近期评论