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
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、(三) 的第22步骤需要还原,此步骤导致样例测试报错,调整为仅web应用情况下,才支持内容协商功能
(1)还原 /common/config/main.php 在第22步骤所做的编辑
(2)编辑 /backend/config/main.php、/frontend/config/main.php
注:如果请求中没有检测到语言, 使用 [[languages]] 第一个配置项。
'bootstrap' => ['log', 'contentNegotiator'],
'components' => [
'contentNegotiator' => [
'class' => 'yii/filters/ContentNegotiator',
'languages' => [
'en-US',
'zh-CN',
],
],
],
(3)编辑 /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',
],
],
],
删除
'response' => [
'format' => yii/web/Response::FORMAT_JSON,
],
5、打开 Windows PowerShell,执行 init 命令并选择 dev 作为环境,然后重新配置数据库连接
./init 0 yes Yes Yes Yes Yes Yes
6、运行所有的样例测试,符合预期,如图2
vendor/bin/codecept run
7、要开始编写 API 测试,创建 API 测试套件,运行命令,如图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、编辑 /api/tests/api.suite.yml 以启用该套件的模块
actor: ApiTester
modules:
enabled:
- REST:
url: /v1
depends: Yii2
- /api/tests/Helper/Api
config:
- Yii2
9、创建测试:获取用户列表(user/IndexEmpty),如图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]],该属性指定应用的版本,默认为’1.0’, 配置为:1.0.0,编辑 /api/config/main.php,此值应与 Git 上的 tag 保持一致
'version' => '1.0.0',
11、编辑 /api/tests/_support/Helper/Api.php,添加 获取当前版本号(次版本号.修订号) 的方法
<?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
vendor/bin/codecept build -- -c api
13、/api/tests/_support/_generated/ApiTesterActions.php 成功生成,新增方法 getMinorPatch(),查看,如图6
14、安装 flow/jsonpath ,以检查响应的结构,如图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、需要为每个测试实现一个公共方法,让 indexIsJson 通过 REST API 测试获取用户列表(用户列表为空、JSON响应),让 indexIsXml 通过 REST API 测试获取用户列表(用户列表为空、XML响应),编辑 /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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期,如图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、创建测试:获取用户列表(user/Index)
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
<?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
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}: 返回用户 {id} 的详细信息,创建测试:获取用户详情
vendor/bin/codecept generate:cest api user/View -c api
21、编辑 /api/tests/api/user/ViewCest.php,获取用户详情(用户ID:{id},不存在/用户ID:{id},的状态为已删除/获取用户详情成功)
<?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
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: 创建一个新用户,创建测试:创建用户
vendor/bin/codecept generate:cest api user/Create -c api
24、编辑 /api/tests/api/user/CreateCest.php,支持(创建用户成功、数据验证失败:{firstErrors})
<?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
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}: 更新一个用户,复制 /api/tests/api/user/CreateCest.php 为 /api/tests/api/user/UpdateCest.php,更新用户(用户ID:{id},不存在/数据验证失败:{firstErrors}/更新用户成功),编辑
<?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、运行测试,获取详细的输出,可看到一步一步的行为报告,符合预期
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}: 删除用户,复制 /api/tests/api/user/ViewCest.php 为 /api/tests/api/user/DeleteCest.php,删除用户(用户ID:{id},不存在/删除用户成功),编辑
<?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
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: 显示关于末端 /users 支持的动词;OPTIONS /users/{id}: 显示关于末端 /users/{id} 支持的动词,复制 /api/tests/api/user/IndexCest.php 为 /api/tests/api/user/OptionsCest.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 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,获取详细的输出,可看到一步一步的行为报告,符合预期
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、运行所有的样例测试,符合预期,如图10
vendor/bin/codecept run
原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/tech/webdev/181083.html
