多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Yii 2 单元测试权威指南:从 PHPUnit 基础到框架级测试与 Docker 集成

Yii 2 单元测试权威指南:从 PHPUnit 基础到框架级测试与 Docker 集成 后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载单元测试是保障代码质量的第一道防线它针对单个代码单元通常是一个类的方法通过不同的输入参数验证方法是否返回预期结果。在 Yii 2 项目中单元测试体系建立在 PHPUnit可选搭配 Codeception之上既适用于你基于 basic / advanced 模板开发的应用也适用于 Yii 2 框架自身的回归测试。本文以官方指南 docs/guide/test-unit.md 为主线结合当前仓库中完整的测试基础设施tests/README.md、phpunit.xml.dist、tests/TestCase.php 等为你呈现一套可阅读、可复制、可运行的单元测试实战方案。什么是单元测试单元测试Unit Test验证的是单个代码单元是否符合预期给定不同的输入参数测试断言类的某个方法返回了期望的结果。它通常由编写被测类的开发者本人编写因为只有作者最清楚类内部的行为契约与边界条件。在 Yii 2 中单元测试构建在PHPUnit之上并且可选地支持Codeception作为更高层的测试框架封装。官方指南建议在深入之前先熟悉这两者的文档Codeception 为 Yii 框架提供的集成说明Codeception for YiiCodeception 的单元测试章节Codeception Unit TestsPHPUnit 官方手册中从第 2 章开始的编写测试部分Writing Tests for PHPUnit。这些外部资料用于理解断言语法、数据提供器Data Provider、测试替身Test Double等通用概念而 Yii 2 仓库自身则为这些通用能力提供了框架层面的落地支撑详见下文测试引导与基类一节。应用项目中的单元测试basic 与 advanced 模板如果你的项目是基于advanced 模板起步的官方指南指出应参考该模板自带的Testing测试指南来运行测试其中涵盖了codeception.yml、common/tests、frontend/tests、backend/tests的完整目录划分与执行方式。如果你的项目是基于basic 模板起步的则应查看模板 README 中的 Testing 一节了解如何在tests/目录下运行单元测试与功能测试。需要说明的是basic 与 advanced 应用模板分别维护在各自独立的模板仓库中当前仓库是 Yii 2 框架核心yiisoft/yii2并不包含这两个应用模板本身。因此运行模板自带测试的细节请以对应模板仓库的文档为准而下面将要展开的框架自身单元测试则是当前仓库内真实存在、可直接运行的测试体系。运行 Yii 2 框架自身的单元测试官方指南指出要运行 Yii 2 框架自身的单元测试请按照 docs/internals/getting-started.md 中描述的流程准备开发环境其中进一步指向 docs/internals/git-workflow.md 说明贡献者的 Git 工作流。在此基础上tests/README.md 给出了最完整的运行说明。测试目录结构框架测试的目录布局如下tests/ ├── data/ # 测试模型、配置及其他测试数据 │ └── config.php # 数据库与缓存后端的配置 ├── framework/ # 框架单元测试主体 └── runtime/ # Yii 测试应用test app的运行时目录其中 tests/data/config.php 集中管理数据库与缓存后端的连接配置tests/framework/ 按框架命名空间镜像组织测试类base/、db/、web/、validators/、i18n/、rest/、widgets/等子目录与框架源码一一对应。前置条件安装 PHPUnit在仓库根目录执行composer update安装全部 Composer 依赖。运行全部测试在 Yii 2 仓库根目录直接执行phpunitPHPUnit 会读取根目录的 phpunit.xml.dist 配置将./tests作为测试套件目录并以 tests/bootstrap.php 作为引导脚本。只运行特定分组的测试phpunit --groupmysql,base,i18n分组group通过测试类/方法的group注解声明。例如 tests/framework/base/ComponentTest.php 中class ComponentTest extends TestCase上方就有group base注解。你可以用以下命令查看当前仓库支持的所有分组phpunit --list-groups结合 tests/test-local.sh 与各数据库测试文件可以看到仓库实际使用的分组包括mysql、pgsql、mssql、oci、caching、db、base、i18n等还可以用--exclude-group db之类的参数排除不感兴趣的分组详见下文 Docker 化测试。运行单个测试类phpunit tests/framework/base/ComponentTest.php这条命令适合在改动框架源码后只针对受影响模块做快速回归验证。例如ComponentTest验证了 Yii 2 组件机制属性、事件、行为、克隆语义等的完整行为契约。PHPUnit 配置解析phpunit.xml.distphpunit.xml.dist 是 Yii 2 框架测试的 PHPUnit 配置模板逐项说明如下配置项值作用bootstrap./tests/bootstrap.php指定测试引导脚本先于任何测试类加载执行colorstrue终端输出彩色结果convertErrorsToExceptionstrue将 PHP 错误转为异常测试中任何错误都会导致失败convertNoticesToExceptionstrueNotice 级别问题同样升级为异常严格暴露隐患convertWarningsToExceptionstrueWarning 级别问题同样升级为异常executionOrderdefault按默认顺序执行测试failOnRiskytrue有风险如无有效断言的测试记为失败failOnWarningtrue有警告的测试记为失败printerClassyiiunit\ResultPrinter使用框架自定义的结果打印器stopOnFailurefalse遇到首个失败不中断跑完全部测试测试套件定义将所有./tests目录纳入同一个 Yii Test Suite。同时配置了代码覆盖率规则framework/目录下的 PHP 文件纳入覆盖统计并排除.phpstorm.meta.php、framework/bootstrap、framework/messages、framework/requirements、framework/base下以Exception.php结尾的文件等不适合做覆盖率统计的目标。你可以复制一份为phpunit.xml覆盖这些默认配置例如本地需要调整stopOnFailure或覆盖率范围时。测试引导与基类框架测试的地基bootstrap.php 做了什么tests/bootstrap.php 是 PHPUnit 的引导脚本其职责包括打开全部错误报告error_reporting(-1)并关闭 Yii 的错误处理器YII_ENABLE_ERROR_HANDLERfalse让测试中的错误直接暴露给 PHPUnit定义测试环境常量YII_DEBUGtrue、YII_ENVtest引入 Composer 自动加载器与 framework/Yii.php设置yiiunit别名指向tests目录若环境变量IS_LOCAL_TESTS存在Docker 环境下会设置见 tests/docker-compose.yml则将yiiunit/runtime与runtime指向/tmp/runtime避免污染仓库内目录引入 tests/TestCase.php 定义的yiiunit\TestCase基类。TestCase 基类为框架测试定制的工具集tests/TestCase.php 中yiiunit\TestCase继承自PHPUnit\Framework\TestCase为所有框架测试提供统一能力mockApplication($config, $appClass)/mockWebApplication($config, $appClass)创建 Yii 控制台/Web 测试应用并填充Yii::$app。默认应用id为testappbasePath指向 tests 目录Web 变体还会配置request组件的cookieValidationKey、脚本路径与bower/npm别名方便涉及视图资源与请求的测试tearDown()自动销毁应用每个测试结束后调用destroyApplication()将Yii::$app置空并先关闭 session保证测试之间互不污染——这是 Yii 框架测试能够成百上千个连续运行的根基tearDownAfterClass()冲刷日志类级测试结束后调用Yii::getLogger()-flush()确保日志目标中的缓存被落盘getParam($name, $default)读取 tests/data/config.php 中的测试参数如数据库连接数组switchDbConnection($db)按配置热切换Yii::$app-db的 DSN/用户名/密码用于跨数据库断言同一套行为invokeMethod()/getInaccessibleProperty()/setInaccessibleProperty()借助反射调用私有/受保护方法与读写私有属性PHP 8.1 之前需要setAccessible(true)代码中已做了版本兼容处理assertEqualsWithoutLE()/assertContainsWithoutLE()忽略换行符差异做字符串断言避免跨平台\r\n干扰assertEqualsAnyWhitespace()/assertSameAnyWhitespace()/sanitizeWhitespaces()忽略 Unicode 空白差异的断言解决 ICU 72 变更带来的空白处理差异问题assertIsOneOf($actual, array $expected)断言实际值属于期望值集合之一配合 tests/IsOneOfAssert.php 实现。以 tests/framework/base/ComponentTest.php 为例可以看到框架测试的典型写法setUp()中调用mockApplication()创建测试应用并实例化被测组件testClone()验证组件克隆后行为与事件处理器被正确剥离testHasProperty()、testCanGetProperty()、testGetProperty()则系统性地断言属性机制的边界包括访问不存在的属性应抛出yii\base\UnknownPropertyException。数据库与缓存测试的配置默认配置与覆盖机制tests/data/config.php 是测试环境的集中配置默认定义了 6 种数据库连接$config [ databases [ cubrid [ dsn cubrid:dbnamedemodb;hostlocalhost;port33000, username dba, password , fixture __DIR__ . /cubrid.sql, ], mysql [ dsn mysql:host127.0.0.1;dbnameyiitest, username root, password root, fixture __DIR__ . /mysql.sql, ], sqlite [ dsn sqlite::memory:, fixture __DIR__ . /sqlite.sql, ], sqlsrv [ dsn sqlsrv:Server127.0.0.1,1433;Databaseyiitest;Encryptno, username SA, password YourStrong!Passw0rd, fixture __DIR__ . /mssql.sql, ], pgsql [ dsn pgsql:hostlocalhost;dbnameyiitest;port5432;, username postgres, password postgres, fixture __DIR__ . /postgres.sql, ], oci [ dsn oci:dbnamelocalhost/FREE;charsetAL32UTF8;, username system, password oracle, fixture __DIR__ . /oci.sql, ], ], ];每种后端都包含dsn、username、password以及对应的建表 SQLfixture文件位于 tests/data/ 下如mysql.sql、sqlite.sql、mssql.sql、postgres.sql、oci.sql。不要直接修改config.php官方推荐创建config.local.php覆盖默认值——该文件会被config.php末尾的include自动加载你只需要操作$config变量即可。例如修改 MySQL 的用户名密码?php $config[databases][mysql][username] yiitest; $config[databases][mysql][password] changeme;这种默认配置 局部覆盖的机制让开发者无需改动仓库内任何受版本控制的文件就能适配自己的数据库环境。测试中如何使用这些配置TestCase::getParam()加载上述配置TestCase::switchDbConnection()则在运行时切换Yii::$app-db的连接参数。这正是 Yii 2 能对同一套 DB 抽象如 Query Builder、ActiveRecord在 MySQL / PostgreSQL / SQL Server / Oracle / SQLite / CUBRID 上做一致性验证的机制。Docker 化测试一行命令拉起完整测试环境test-local.sh 与docker-compose.*.yml文件共同构成了框架测试的 Docker 化方案。第一步准备环境配置进入tests目录复制环境模板cd tests cp .env-dist .env新建的.env文件通过COMPOSE_FILE变量决定启用哪些服务。默认情况下 MySQL、Postgres 等服务都是禁用的。如果只想用 MySQL 测试可以把COMPOSE_FILE修改为COMPOSE_FILEdocker-compose.yml:docker-compose.mysql.yml注意docker-compose.caching.yml和docker-compose.mssql.yml不能与docker-compose.yml合并使用它们各自独立定义完整环境见 tests/README.md 的说明。方式一通过 shell 脚本运行在tests目录下执行test-local.sh第一个参数指定测试场景可选值包括default、caching、mssql、pgsql、mysql后续参数会原样透传给 PHPUnit。例如cd tests sh test-local.sh default --exclude caching,db脚本内部对应关系见 tests/test-local.sh 源码场景执行的命令default启动默认容器栈运行vendor/bin/phpunit -v全量测试caching设置COMPOSE_FILEdocker-compose.caching.yml运行--group caching --exclude-group dbmssql独立栈先创建yiitest数据库再运行--group mssqlpgsql合并docker-compose.pgsql.yml运行--group pgsqlmysql合并docker-compose.mysql.yml运行--group mysql方式二手动运行也可以手动启动容器并进入执行docker compose up -d docker compose exec php vendor/bin/phpunit -v注意 tests/docker-compose.yml 会将宿主机的tests/data/config-docker.php挂载为容器内的tests/data/config.php并通过环境变量IS_LOCAL_TESTS1让引导脚本把运行时目录指到/tmp/runtime从而在不污染仓库的前提下完成整套测试。Oracle 测试的特殊要求Oracle 测试与其他后端不同属于特殊场景前置条件宿主机必须安装oci8和pdo_oci两个 PHP 扩展docker-compose.oracle.yml只负责启动 Oracle 数据库容器PHPUnit 仍在宿主机运行执行步骤cd tests COMPOSE_FILEdocker-compose.oracle.yml docker compose up -d --wait cd .. vendor/bin/phpunit -v --group oci cd tests COMPOSE_FILEdocker-compose.oracle.yml docker compose down -v测试结束后用docker compose down -v清理容器与数据卷。编写你自己的单元测试参考框架测试模式为你的 Yii 2 应用编写单元测试时可以直接复用本仓库验证过的模式继承yiiunit\TestCase或你自己的TestCase变体在setUp()中调用mockApplication()/mockWebApplication()准备应用上下文tearDown()由基类自动销毁应用用group注解给测试分类便于用phpunit --group...精确筛选用dataProvider提供多组输入覆盖正常值、边界值与异常输入利用invokeMethod()等反射工具测试私有方法/属性的行为使用assertIsOneOf等自定义断言提升断言语义。示例骨架参考 tests/framework/base/ComponentTest.php 的结构?php /** * group myapp */ class MyServiceTest extends \yiiunit\TestCase { protected function setUp(): void { parent::setUp(); $this-mockApplication([ components [ db [class yii\db\Connection, ...], ], ]); } public function testCalculate(): void { $service new MyService(); $this-assertSame(5, $service-calculate(2, 3)); } }小结Yii 2 的单元测试体系脉络清晰PHPUnit 提供执行引擎Codeception 可选增强tests/目录提供完整的基础设施。对应用开发者而言掌握phpunit --group、数据提供器与TestCase工具方法即可写出高质量的单元测试对框架贡献者而言tests/README.md 给出的目录结构、phpunit.xml.dist 的严格配置、config.local.php的覆盖机制以及 Docker 化的test-local.sh流程让任何人都能在一台机器上复现框架全量测试——这正是 Yii 2 号称Fast, Secure and Professional背后真实存在的质量保障体系。赞分享后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载相关推荐Yii 2 单元测试完全指南从 PHPUnit 基础到框架源码级测试实践Yii 2 单元测试完全指南从 PHPUnit 基础到框架源码级测试实践 单元测试用于验证一段最小单元代码通常是一个类的方法是否按预期工作给定不同的输入后端Web框架Yii 2 单元测试实战指南基于 PHPUnit 与 Codeception 的框架测试体系Yii 2 单元测试实战指南基于 PHPUnit 与 Codeception 的框架测试体系 本篇指南聚焦 Yii 2 框架的单元测试Unit Testin后端Web框架Yii 2 单元测试实战指南从框架自身测试体系到项目应用Unit Testing in Yii 2Yii 2 单元测试实战指南从框架自身测试体系到项目应用Unit Testing in Yii 2 单元测试验证单个代码单元在 OOP 中最基本的单元是后端Web框架上一篇Soularr与Slskd集成详解打造个人音乐库自动获取系统下一篇重构网盘下载逻辑LinkSwift如何破解8大平台限速壁垒创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表