ThinkPHP 5.1 集成 PHPUnit 8 测试框架

本项目仅适用于运行 PHP7.2 以上的环境!对于低版本 PHP 请根据需要调整 PHPUnit 的版本!

声明

由于原项目 think-testing 长久不更新导致无法兼容最新版本的PHP和PHpstrom,无法像java一样进行单元调试。所以在此改造一番。

  • PHPUnit基础请参考PHPUnit
  • 官方文档

版本号参考

PHP 版本 PHPUnit 版本
7.3, 7.2 8
7.1 (仅安全更新,2019 年 12 月 1 日起停止支持) 7
7.0 (已经停止支持) 6
5.6 (已经停止支持) 5
5.5, 5.4, 5.3 (已经停止支持) 4

教程

  1. 首先你要学会使用 Composer,可以参考 laravel-china 的这篇教程,里面包含了从安装 Composer 开始到配置国内镜像加速源全套流程,速度不佳还可以尝试使用 Packagist / Composer 中国全量镜像(含安装教程) 或者 阿里云 Composer 全量镜像。请尽可能使用比较新的 Composer 版本!截止我写这篇文章时,我的 Composer 版本号是 Composer version 1.8.6 2019-06-11 15:03:05(使用 composer --version 查看)

  2. 在自己的项目下安装 PHPUnit 扩展和必要的 symfony/dom-crawler 扩展,以及使用的 think-testing 包中会用到的 topthink/think-helper,参考命令:

    $ composer require phpunit/phpunit=^8 --dev
    $ composer require symfony/dom-crawler=^2.8.8 --dev
    $ composer require topthink/think-helper
    

    请注意安装的版本号,再次强调:

    **PHPUnit 的版本号要和 PHP 的版本相对应!并不是越高越好! ** 具体的版本号请参考开头的表格,把 =^8 替换成对应的数字即可。

    symfony/dom-crawler 扩展之所以使用 2.8.8~3.0 以前版本主要是为了模拟原 think-testing 项目中模拟爬取网页 DOM 节点部分所使用的包,因为我的开发不涉及页面部分故高版本未作测试。

    topthink/think-helper 扩展会自动根据你当前的 ThinkPHP 主框架版本确定,所以无需指定版本号。

  3. 在自己的项目根目录下创建 tests 文件夹,修改 composer.json 文件的 "autoload" 部分:在 "psr-4"后面的列表中添加:

    "tests\\": "tests",
    "think\\": "thinkphp/library/think",
    "traits\\": "thinkphp/library/traits"
    

    添加完成的 "autoload" 部分应该长这样:

    "autoload": {"psr-4": {"app\\": "application","tests\\": "tests","think\\": "thinkphp/library/think","traits\\": "thinkphp/library/traits"}
    }
    

    完成后在项目根目录执行 composer update 生成 autoload 文件

  4. 在任意位置新建文件夹并进入,在新建的这个文件夹里使用 composer require topthink/think-testing 安装官方的 think-testing 项目,拷贝 vendor/topthink/think-testing/src/ 目录下除 config.php 文件和 command 文件夹外所有文件到自己的项目根目录下的 tests 文件夹中,修改所有文件的 namespace 命名空间为 tests

  5. 在你的项目根目录创建名为 phpunit.xml 的文件,用于指定自动测试,内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <phpunit backupGlobals="false"backupStaticAttributes="false"colors="true"convertErrorsToExceptions="true"convertNoticesToExceptions="true"convertWarningsToExceptions="true"processIsolation="false"stopOnFailure="false"><testsuites><testsuite name="Application Test Suite"><directory suffix=".php">./tests/</directory></testsuite></testsuites><filter><whitelist><directory suffix=".php">application/</directory></whitelist></filter>
    </phpunit>
    
  6. tests/TestCase.php 文件中添加 __construct 方法如下:

    public function __construct(?string $name = null, array $data = [], string $dataName = '') {// 引入需要的环境require_once __DIR__ . '/../thinkphp/base.php';// 初始化 App 对象,并将 APP_PATH 指向项目的 application 目录App::getInstance()->path(__DIR__ . '/../application/')->initialize();parent::__construct($name, $data, $dataName);
    }
    
  7. tests/TestCase.php 文件中添加 $baseUrl 的成员变量如下:

    protected $baseUrl = '';
    

    注意:如果开启了强制路由的选项,那这里要和你路由中配置的域名一致 ,如果不一致会报莫名其妙的 500 错误。

  8. 从根目录下运行 ./vendor/bin/phpunit 测试单元测试是否配置成功,如果出来的结果是类似于:

    $ ./vendor/bin/phpunit
    PHPUnit 8.2.4 by Sebastian Bergmann and contributors.Time: 6 ms, Memory: 2.00 MBNo tests executed!
    

    那么恭喜你,环境是没啥问题了。

  9. 最后一步,编写一个简单的测试,在 tests 文件夹中创建名为 BasicTest.php 的测试文件,内容如下:

    <?php
    namespace tests;class BasicTest extends \tests\TestCase {public function testBasicFunctions() {$this->assertTrue(true);$this->assertEquals(2, 1+1);$app = new \app\index\controller\Index();// 假设 index/index/index 方法返回的字符串中包含 "index"$this->assertStringContainsString('index', $app->index());}public function testThinkPHPStyleTests() {// 假设我访问 "/" 会看到 "index"$this->visit('/')->see('index');}
    }
    

    从根目录下运行 ./vendor/bin/phpunit ,如果出来的结果是类似于:

    $ ./vendor/bin/phpunit
    PHPUnit 8.2.4 by Sebastian Bergmann and contributors...                                                                  2 / 2 (100%)Time: 26 ms, Memory: 6.00 MBOK (2 tests, 5 assertions)
    

    恭喜你,大功告成,你接下来就可以按照网上的 PHPUnit 的教程开始编写测试了。在我的测试环境下(OSX 10.13, Homebrew PHP 7.2, PHPUnit 8),所有的测试,只要是放到 tests 文件夹下且保持命名空间正确就可以自动测试,按照需要测试的类首字母顺序进行。

常见问题

  1. 错误:xxx Not Found

    一般是之前 composer require 的部分没有装好,回去重新执行即可。

  2. 测试结果提示:

    OK, but incomplete, skipped, or risky tests!
    Tests: 4, Assertions: 10, Risky: 1.
    

    或者是红字:

    FAILURES!
    Tests: 5, Assertions: 10, Failures: 1.
    

    请参考 PHPUnit 相关资料,第一个可能是因为有测试里面什么都没执行,第二个是因为有测试失败了

  3. 完全不能执行,提示错误:

    include(): Filename cannot be empty
    

    或者

    think\exception\ErrorException: include(): Filename cannot be empty
    

    之前 __construct 那一步没做好,或者是 base.php 没引对,或者是 APP_PATH 配置错了

  4. 错误:

    A request to xxx failed. Received status code 500.
    

    恭喜,最难搞的错误之一。原因很多,但是不明确,可能是使用了高版本的 PHP 搭配了低版本的 PHPUnit:比如 PHP 7.2 中的 each() 函数已经 deprecated 了,但是 PHPUnit 6 中仍有使用(也是造成我默认项目测试不了的原因);也可能是强制路由模式下路由配置不正确,没有命中任何路由;也有可能是因为 $baseUrl 或者其他域名相关的配置不正确导致的。可以创建空项目进行尝试,如果空项目正常说明是原来项目配置有问题或者路由不对。

  5. 提示:

    PHP Fatal error:  Class tests\HttpException may not inherit from final class (PHPUnit\Framework\ExpectationFailedException) in /path/to/your/project/tests/HttpException.php on line 7
    

    修改 InteractWithPages.php 第 484 行为:

    throw new \PHPUnit\Framework\ExpectationFailedException($message);
    

    并删除 tests/HttpException.php 文件

在PhpStorm 中使用单元调试

1. 配置PhpStorm

1.配置phpunit.phar路径
2.配置phpunit.xml路径
3.配置启动文件路径

2.点击run

3.结果

[欢迎Start](https://github.com/AndyYoungCN/think-tests)

ThinkPHP 集成 PHPUnit 8 测试框架进行单元测试相关推荐

  1. 浅谈Spring测试框架+junit4单元测试原理

    Spring的主要测试框架核心: 3个接口 1TestContext:负责持有一个当前测试的上下文 2TestContextManger: (1)每次启动都会创建,管理一个TestContext (2 ...

  2. python+selenium+unittest测试框架1-unittest单元测试框架和断言

    unittest单元测试框架和断言 一.unittest单元测试框架简介 1.导入unittest模块 import unittest 2.定义测试类 class Login(unittest.Tes ...

  3. python测试框架untest_Python单元测试框架 unittest详解

    以上是函数的测试,类的测试与函数的测试及其相似 1 import unittest2 3 #-*-coding:utf-8-*- 4 classAnonymousSurvey():5 "&q ...

  4. Android测试最新框架,Android单元测试-常见的方案比较

    前言 本文将介绍在Android Studio中,android单元测试的介绍和实现.相关代码托管在github上的AndroidJunitDemo中,涉及到的用例代码收集于google官方提供的测试 ...

  5. PHP自动测试框架Top 10

    2019独角兽企业重金招聘Python工程师标准>>> 对于很多PHP开发新手来说,测试自己编写的代码是一个非常棘手的问题.如果出现问题,他们将不知道下一步该怎么做.花费很长的时间调 ...

  6. 基于Python的接口自动化unittest测试框架和ddt数据驱动详解

    引言 在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条接口测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行,还有在运行大量的接口测试用 ...

  7. maven TestNg 测试框架 not found

    在用TestNG测试框架进行单元测试时,在我的pom.xml中写的依赖: <dependency><groupId>org.testng</groupId>< ...

  8. Spock测试框架如何Mock静态方法

    1. 问题场景 在写单元测试时,难免会遇到需要Mock的静态方法.当使用Spock测试框架时,Spock提供Moc静态方法Mock只支持Groovy语言,无法支持Java语言实现的静态方法Mockin ...

  9. 单元测试及NUnit测试框架简介(二)

    一.单元测试框架的选择 在选择单元测试框架时,可以从以下几个方面去考虑: 支持自动检测注册用例:框架能否支持简单地构造用例并自动注册测试用例到测试框架中: 支持测试Fixture:即是否支持为一组测试 ...

最新文章

  1. 深证信息等三方拟联合开展大数据研究
  2. 在html利用canvas蚂蚁,html5 利用canvas实现简单的人物走动
  3. 自动生成用户名,密码的方法
  4. sql去除重复语句(转)
  5. IOS开发之表视图(UITableView)
  6. Oracle rman备份和还原恢复数据库
  7. iframe跨域调用js_郑州Web前端基础学习之JS跨域知识梳理
  8. 江淮汽车:受疫情和芯片短缺影响 Q1预亏3.07亿元
  9. linux内核模块签名,linux内核模块签名
  10. matplotlib polar 雷达图
  11. Netty工作笔记0020---Selectionkey在NIO体系
  12. px,em,rem单位转换工具
  13. 图书管理系统(数据库)
  14. 国内三大常见核心期刊体系简介——CSSCI、CSCD与中文核心期
  15. 定时器控制一个ADC实现双通道采样(TIM+ADC+DMA)
  16. 正十二面体二面角的一种求法
  17. 开发QQ桌球瞄准器(5):使用注册表保存配置
  18. app 原形设计常用工具总结
  19. java 拼图_拼图延迟的历史-Oracle正式将Java 9的发布日期推迟到2017年
  20. C Primer Plus中文 第6版勘误表

热门文章

  1. EST:李芳柏团队揭示微生物介导的砷氧化耦合硝酸还原
  2. linux 极简统计分析工具 datamash 必看教程
  3. Nature:人体菌群研究的25个里程碑
  4. Co-occurrence网络图在R中的实现
  5. Microbiome:肠道菌群失衡促进高血压
  6. Python使用matplotlib可视化箱图、seaborn中的boxplot函数可视化分组箱图、在箱图中添加抖动数据点(Dot + Box Plot)
  7. pandas使用pct_change计算数据列的百分比变化、环比变化率:计算当前元素和前一个元素之间的百分比变化、使用style函数指定format的格式:百分比、缺失值替换、用颜色标注极大值和极小值
  8. R语言row.names函数为dataframe、matrix设置行名称实战
  9. 基准分类模型、分类应用(多分类数字识别、疾病预测、欺诈检测)、监督学习总结
  10. 网络抓包wireshark