Codeception 实战
Codeception 测试 Php 代码
一、一句话概述
使用 cc 进行单元测试,保证现有代码质量,为以后维护与重构提供支撑。
二、目标
- 安装配置 cc
- 编写测试代码,简化开发与最大化稳定性和可维护性
三、测试的类型
1. 单元测试(UT)
- 执行一段与其他代码完全隔离的代码单元
- 断言代码行为
- 描述用例的预期
2. 功能测试(FT)
- 执行应用(客户端)请求
- 断言返回值
- 描述应用预期行为
- 依赖框架
3. Web 服务测试
- 通过 http client 执行 api 请求
- 对 api 返回值断言
- 描述 api 行为
四、系统要求
- PHP 5.4+
- json 扩展
- mbstring 扩展
- xdebug 扩展(生成覆盖率报告)
下载安装配置 php扩展 xdebug
版本选用最新稳定版: 2.6.1
wget https://pecl.php.net/get/xdebug-2.6.1.tgz
tar xvf xdebug-2.6.1.tgz
cd xdebug-2.6.1
/path/to/phpize
./configure --enable-xdebug
make
make install
在 php.ini 文件中添加此行:
zend_extension="/wherever/you/put/it/xdebug.so"
查看是否安装上:
php -i | grep xdebug
五、安装配置与运行 Codeception
wget http://codeception.com/codecept.phar # 不需要解压
php codecept.phar help # 帮助文档
php codecept.phar bootstrap # 创建 test & codeception.yml 到当前文件夹
php codecept.phar build # 通过配置生成必要的类,每次修改配置都需要运行次命令
php codecept.phar run {suite_name} # 不跟 suite name 即是运行全部
php codecept.phar run api ThingTest.php
php codecept.phar run api ThingTest.php:method
配置与代码示例
地址:https://github.com/wdy1184/CodeceptionExampleWithYii2
六、测试代码格式
codeception 提供了两种写测试代码的方式
- Cept: 一个独立的测试文件。可以写一套测试流程。
- Cest: 一个类文件,多个测试写在一个类中。
- PHPUnit: 支持 phpunit 原生测试框架的格式
七、与Yii2集成
配置:
_bootstrap.php 代码
<?php
defined('APP_PATH') or define('APP_PATH', dirname(dirname(__FILE__)));
// 注册 Composer 自动加载器
// 包含 Yii 类文件
require(__DIR__ . '/../../psservice/libs/envFun.php');
require(__DIR__ . '/../../vendor/autoload.php');
// 环境变量配置
defined('YII_DEBUG') or define('YII_DEBUG', getYaconfEnv('YII_DEBUG'));
defined('YII_ENV') or define('YII_ENV', getYaconfEnv('YII_ENV'));
defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER', getYaconfEnv('YII_ENABLE_ERROR_HANDLER'));
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
// 暂时向下兼容老文件
require(__DIR__ . '/../../config/errorCode.php');
require(__DIR__ . '/../../config/constant.php');
Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend');
Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console');
Yii::setAlias('@psservice', dirname(dirname(__DIR__)) . '/psservice');
Yii::setAlias('@config', dirname(dirname(__DIR__)) . '/config');
$config = require(APP_PATH . '/../config/web.php');
Cest 代码示例
<?php
namespace tests\api;
use backend\models\user\EduOcrTourist;
use backend\models\user\EduOcrUser;
use backend\modules\user\services\UserEntity;
use config\UserCacheKey;
use psservice\models\user\WxEduUser;
use tests\ApiTester;
class UserControllerCest
{
private $token;
public function _before(ApiTester $I)
{
}
/**
* 用户登录
* @param ApiTester $I
*/
public function actionLoginTest(ApiTester $I)
{
$mobile = '18510473853';
$token = $I->amUserLogin($mobile);
$I->sendCommandToRedis('select', getPsYaconfEnv('PS_OCR_SINGLE_REDIS_DATABASE_1'));
$userRedisInfo = $I->grabFromRedis(sprintf(UserCacheKey::USER_INFO, $token));
$userRedisInfo = json_decode($userRedisInfo, 1);
codecept_debug($userRedisInfo);
$I->assertGreaterThan(0, $userRedisInfo['userId']);
$I->assertEquals(0, $userRedisInfo['touristUserId']);
$I->assertEquals(UserEntity::$roleMap['user'], $userRedisInfo['role']);
$I->assertEquals($mobile, $userRedisInfo['mobile']);
$I->assertLessOrEquals(10, (time() - strtotime($userRedisInfo['loginTime'])));
$I->seeRecord(WxEduUser::className(), ['UserId' => $userRedisInfo['commonUserId']]);
}
/**
* 游客登录
* @param ApiTester $I
*/
public function actionTouristLoginTest(ApiTester $I)
{
$token = $I->amTouristLogin('6CB7B05E-DE62-415A-96CF-6D57B666F939');
$I->sendCommandToRedis('select', getPsYaconfEnv('PS_OCR_SINGLE_REDIS_DATABASE_1'));
// $userRedisInfo = $I->grabFromRedis(sprintf(UserCacheKey::TOURIST_INFO, $token)); // 机缘巧合下,没有使用 touristInfo 常量
$userRedisInfo = $I->grabFromRedis(sprintf(UserCacheKey::USER_INFO, $token));
$userRedisInfo = json_decode($userRedisInfo, 1);
codecept_debug($userRedisInfo);
$I->assertGreaterThan(0, $userRedisInfo['id']);
$I->seeRecord(EduOcrTourist::className(), ['deviceId' => '6CB7B05E-DE62-415A-96CF-6D57B666F939']);
}
/**
* 登出
* @param ApiTester $I
*/
public function actionLogoutTest(ApiTester $I)
{
$this->token = $I->amUserLogin('18510473853');
$I->sendPOST('/user/user/logout', [
'token' => $this->token,
'deviceId' => '6CB7B05E-DE62-415A-96CF-6D57B666F939',
]);
$I->seeResponseContainsJson(['code' => 99999]);
}
/**
* 登录用户信息
*/
public function actionInfoTest(ApiTester $I)
{
$mobile = '18510473853';
$this->token = $I->amUserLogin($mobile);
$I->sendGET('/user/user/info', [
'token' => $this->token,
]);
$ret = json_decode($I->grabResponse(), 1);
$I->seeRecord(EduOcrUser::className(), ['id' => $ret['data']['userId'], 'mobile' => $mobile]);
}
}
八、增加自定义方法
tests/_support/Helper/{suite_name}.php
在其中增加方法后,可以通过 ApiTester 的对象 $I 进行调用。
九、运行测试代码生成测试报告(代码覆盖率)
php codecept.phar run -coverage --coverage-html --coverage-xml
测试报告会在 tests/_output/coverage/
中生成。
通过设定 nginx 静态服务器,可以查看测试报告。如:
十、利用测试用例进行重构
步骤:
- 编写测试代码
- 持续维护测试代码,提高测试代码覆盖率
- 运行测试代码使其通过。并不断重复 1、2、3 步骤
- 代码库越来越庞杂
- 重构
- 合并相似循环、方法、类
- 提取方法
- 等等
- 运行测试用例,找到失败的用例
- 修改重构后的代码,使其通过测试用例,并重复 5、6、7 步骤
十一、利用测试用例,快速了解新代码
steps
会在执行的时候打印出执行的断言,有助于观察测试用例做了什么,以及怎么使用你写的接口。
即测试用例是 : self-document 的。
php codecept.phar run api --steps # steps 会在执行的时候打印出执行的断言
Codeception 实战的更多相关文章
- SSH实战 · 唯唯乐购项目(上)
前台需求分析 一:用户模块 注册 前台JS校验 使用AJAX完成对用户名(邮箱)的异步校验 后台Struts2校验 验证码 发送激活邮件 将用户信息存入到数据库 激活 点击激活邮件中的链接完成激活 根 ...
- GitHub实战系列汇总篇
基础: 1.GitHub实战系列~1.环境部署+创建第一个文件 2015-12-9 http://www.cnblogs.com/dunitian/p/5034624.html 2.GitHub实战系 ...
- MySQL 系列(四)主从复制、备份恢复方案生产环境实战
第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...
- Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- 给缺少Python项目实战经验的人
我们在学习过程中最容易犯的一个错误就是:看的多动手的少,特别是对于一些项目的开发学习就更少了! 没有一个完整的项目开发过程,是不会对整个开发流程以及理论知识有牢固的认知的,对于怎样将所学的理论知识应用 ...
- asp.net core 实战之 redis 负载均衡和"高可用"实现
1.概述 分布式系统缓存已经变得不可或缺,本文主要阐述如何实现redis主从复制集群的负载均衡,以及 redis的"高可用"实现, 呵呵双引号的"高可用"并不是 ...
- Linux实战教学笔记08:Linux 文件的属性(上半部分)
第八节 Linux 文件的属性(上半部分) 标签(空格分隔):Linux实战教学笔记 第1章 Linux中的文件 1.1 文件属性概述(ls -lhi) linux里一切皆文件 Linux系统中的文件 ...
- Linux实战教学笔记07:Linux系统目录结构介绍
第七节 Linux系统目录结构介绍 标签(空格分隔):Linux实战教学笔记 第1章 前言 windows目录结构 C:\windows D:\Program Files E:\你懂的\精品 F:\你 ...
- Linux实战教学笔记06:Linux系统基础优化
第六节 Linux系统基础优化 标签(空格分隔):Linux实战教学笔记-陈思齐 第1章 基础环境 第2章 使用网易163镜像做yum源 默认国外的yum源速度很慢,所以换成国内的. 第一步:先备份 ...
随机推荐
- Win10下搭建Git服务器
一. 搭建Git服务器环境前的必要准备 1.Windows10 2.Java环境 3.GitBlit服务器 4.Git版本管理工具 二. 开始搭建 第一步.安装JAVA运行环境 https://www ...
- bat脚本自定义魔兽warIII运行分辨率,去黑边
我们一般平时安装完WarIII后运行时的分辨率默认是800*600,导致有黑边的存在.所以我写了一个bat脚本来自定义WarIII的运行分辨率.需要以管理员身份运行. 下载链接: 链接:https:/ ...
- kerberos环境storm配置:Running Apache Storm Securely
Running Apache Storm Securely Apache Storm offers a range of configuration options when trying to se ...
- 史上最全的springboot导出pdf文件
最近项目有一个导出报表文件的需求,我脑中闪过第一念头就是导出pdf(产品经理没有硬性规定导出excel还是pdf文件),于是赶紧上网查看相关的资料,直到踩了无数的坑把功能做出来了才知道其实导出exce ...
- js导出excel表格并生成多sheet
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- MYSQL的group by笔记
对应的表数据如下 现在的需求是要找出dcid为9951,9957,9064共同拥有的good_code. 第一种方案是 SELECT a.good_code FROM ( SELECT good_co ...
- SQL慢查询测试实践
1.开启慢查询的目的 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能. 2.设置mysql慢查询 方法一:全局变量设置(临时生效) ...
- 《HelloGitHub》第 29 期
公告 月刊现已支持 RSS 订阅 <HelloGitHub>第 29 期 兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. ...
- docker-swarm建立本地集成开发环境
在k8s出现之后,docker-swarm使用的人越来越少,但在本地集成开发环境的搭建上,使用它还是比较轻量级的,它比docker-compose最大的好处就是容器之间的共享和服务的治理,你不需要li ...
- 基于python脚本,实现Unity全平台的自动打包
转载请标明出处:http://www.cnblogs.com/zblade/ 0. 概述 本文主要针对项目中自动打包过程进行调研,实现用python脚本来打出win/android/ios三个平台下的 ...