ThinkPHP 集成 PHPUnit 8 测试框架进行单元测试
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 |
教程
首先你要学会使用 Composer,可以参考 laravel-china 的这篇教程,里面包含了从安装 Composer 开始到配置国内镜像加速源全套流程,速度不佳还可以尝试使用 Packagist / Composer 中国全量镜像(含安装教程) 或者 阿里云 Composer 全量镜像。请尽可能使用比较新的 Composer 版本!截止我写这篇文章时,我的 Composer 版本号是
Composer version 1.8.6 2019-06-11 15:03:05
(使用composer --version
查看)在自己的项目下安装 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 主框架版本确定,所以无需指定版本号。在自己的项目根目录下创建
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 文件在任意位置新建文件夹并进入,在新建的这个文件夹里使用
composer require topthink/think-testing
安装官方的 think-testing 项目,拷贝vendor/topthink/think-testing/src/
目录下除config.php
文件和command
文件夹外所有文件到自己的项目根目录下的tests
文件夹中,修改所有文件的namespace
命名空间为tests
。在你的项目根目录创建名为
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>
在
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); }
在
tests/TestCase.php
文件中添加$baseUrl
的成员变量如下:protected $baseUrl = '';
注意:如果开启了强制路由的选项,那这里要和你路由中配置的域名一致 ,如果不一致会报莫名其妙的 500 错误。
从根目录下运行
./vendor/bin/phpunit
测试单元测试是否配置成功,如果出来的结果是类似于:$ ./vendor/bin/phpunit PHPUnit 8.2.4 by Sebastian Bergmann and contributors.Time: 6 ms, Memory: 2.00 MBNo tests executed!
那么恭喜你,环境是没啥问题了。
最后一步,编写一个简单的测试,在
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
文件夹下且保持命名空间正确就可以自动测试,按照需要测试的类首字母顺序进行。
常见问题
错误:xxx Not Found
一般是之前
composer require
的部分没有装好,回去重新执行即可。测试结果提示:
OK, but incomplete, skipped, or risky tests! Tests: 4, Assertions: 10, Risky: 1.
或者是红字:
FAILURES! Tests: 5, Assertions: 10, Failures: 1.
请参考 PHPUnit 相关资料,第一个可能是因为有测试里面什么都没执行,第二个是因为有测试失败了
完全不能执行,提示错误:
include(): Filename cannot be empty
或者
think\exception\ErrorException: include(): Filename cannot be empty
之前
__construct
那一步没做好,或者是base.php
没引对,或者是 APP_PATH 配置错了错误:
A request to xxx failed. Received status code 500.
恭喜,最难搞的错误之一。原因很多,但是不明确,可能是使用了高版本的 PHP 搭配了低版本的 PHPUnit:比如 PHP 7.2 中的 each() 函数已经 deprecated 了,但是 PHPUnit 6 中仍有使用(也是造成我默认项目测试不了的原因);也可能是强制路由模式下路由配置不正确,没有命中任何路由;也有可能是因为
$baseUrl
或者其他域名相关的配置不正确导致的。可以创建空项目进行尝试,如果空项目正常说明是原来项目配置有问题或者路由不对。提示:
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 测试框架进行单元测试相关推荐
- 浅谈Spring测试框架+junit4单元测试原理
Spring的主要测试框架核心: 3个接口 1TestContext:负责持有一个当前测试的上下文 2TestContextManger: (1)每次启动都会创建,管理一个TestContext (2 ...
- python+selenium+unittest测试框架1-unittest单元测试框架和断言
unittest单元测试框架和断言 一.unittest单元测试框架简介 1.导入unittest模块 import unittest 2.定义测试类 class Login(unittest.Tes ...
- python测试框架untest_Python单元测试框架 unittest详解
以上是函数的测试,类的测试与函数的测试及其相似 1 import unittest2 3 #-*-coding:utf-8-*- 4 classAnonymousSurvey():5 "&q ...
- Android测试最新框架,Android单元测试-常见的方案比较
前言 本文将介绍在Android Studio中,android单元测试的介绍和实现.相关代码托管在github上的AndroidJunitDemo中,涉及到的用例代码收集于google官方提供的测试 ...
- PHP自动测试框架Top 10
2019独角兽企业重金招聘Python工程师标准>>> 对于很多PHP开发新手来说,测试自己编写的代码是一个非常棘手的问题.如果出现问题,他们将不知道下一步该怎么做.花费很长的时间调 ...
- 基于Python的接口自动化unittest测试框架和ddt数据驱动详解
引言 在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条接口测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行,还有在运行大量的接口测试用 ...
- maven TestNg 测试框架 not found
在用TestNG测试框架进行单元测试时,在我的pom.xml中写的依赖: <dependency><groupId>org.testng</groupId>< ...
- Spock测试框架如何Mock静态方法
1. 问题场景 在写单元测试时,难免会遇到需要Mock的静态方法.当使用Spock测试框架时,Spock提供Moc静态方法Mock只支持Groovy语言,无法支持Java语言实现的静态方法Mockin ...
- 单元测试及NUnit测试框架简介(二)
一.单元测试框架的选择 在选择单元测试框架时,可以从以下几个方面去考虑: 支持自动检测注册用例:框架能否支持简单地构造用例并自动注册测试用例到测试框架中: 支持测试Fixture:即是否支持为一组测试 ...
最新文章
- 深证信息等三方拟联合开展大数据研究
- 在html利用canvas蚂蚁,html5 利用canvas实现简单的人物走动
- 自动生成用户名,密码的方法
- sql去除重复语句(转)
- IOS开发之表视图(UITableView)
- Oracle rman备份和还原恢复数据库
- iframe跨域调用js_郑州Web前端基础学习之JS跨域知识梳理
- 江淮汽车:受疫情和芯片短缺影响 Q1预亏3.07亿元
- linux内核模块签名,linux内核模块签名
- matplotlib polar 雷达图
- Netty工作笔记0020---Selectionkey在NIO体系
- px,em,rem单位转换工具
- 图书管理系统(数据库)
- 国内三大常见核心期刊体系简介——CSSCI、CSCD与中文核心期
- 定时器控制一个ADC实现双通道采样(TIM+ADC+DMA)
- 正十二面体二面角的一种求法
- 开发QQ桌球瞄准器(5):使用注册表保存配置
- app 原形设计常用工具总结
- java 拼图_拼图延迟的历史-Oracle正式将Java 9的发布日期推迟到2017年
- C Primer Plus中文 第6版勘误表
热门文章
- EST:李芳柏团队揭示微生物介导的砷氧化耦合硝酸还原
- linux 极简统计分析工具 datamash 必看教程
- Nature:人体菌群研究的25个里程碑
- Co-occurrence网络图在R中的实现
- Microbiome:肠道菌群失衡促进高血压
- Python使用matplotlib可视化箱图、seaborn中的boxplot函数可视化分组箱图、在箱图中添加抖动数据点(Dot + Box Plot)
- pandas使用pct_change计算数据列的百分比变化、环比变化率:计算当前元素和前一个元素之间的百分比变化、使用style函数指定format的格式:百分比、缺失值替换、用颜色标注极大值和极小值
- R语言row.names函数为dataframe、matrix设置行名称实战
- 基准分类模型、分类应用(多分类数字识别、疾病预测、欺诈检测)、监督学习总结
- 网络抓包wireshark