开发工具代码质量静态分析Lint格式化【免费下载链接】PHP-CS-FixerA tool to automatically fix PHP Coding Standards issues项目地址https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer点击查看免费下载导读php_unit_construct是 PHP-CS-Fixer 中面向 PHPUnit 测试代码的专用修复规则它能把-assertSame(true, $foo)、-assertEquals(null, $bar)这类通用断言 字面量常量的写法自动改写为语义更精确的专用断言方法-assertTrue($foo)、-assertNull($bar)。本文将以该规则的官方文档为主体结合 Fixer 源码与测试用例完整讲解它的转换原理、assertions配置项、风险边界以及在实际项目中的启用方式帮助你安全地把这条 risky 规则纳入 CI 流程。规则要解决什么问题在 PHPUnit 测试中有两种常见的断言写法// 写法一通用断言 布尔字面量 $this-assertSame(true, $a); $this-assertEquals(false, $b); // 写法二专用断言方法 $this-assertTrue($a); $this-assertFalse($b);两种写法在功能上等价但第二种更直接地表达了断言意图assertTrue/assertFalse/assertNull/assertNotNull一眼就能看出被断言的值是什么测试失败时的语义也更容易理解。php_unit_construct规则的目标就是把文档所述的这类调用PHPUnit assertion method calls like-assertSame(true, $foo)should be written with dedicated method like-assertTrue($foo).自动转换成对应的专用方法。规则的官方定位与风险警告在 PHP-CS-Fixer 的规则体系中该规则有两项重要标注详见 php_unit_construct.rstRISKY高风险规则文档明确警告 —— Fixer could be risky if one is overriding PHPUnits native methods. 如果被测代码或测试基类覆盖了 PHPUnit 的原生断言方法例如自定义了一个assertTrue()并赋予了额外行为那么本规则改写后的代码可能不再走你的自定义实现导致测试行为发生变化。这正是它被归入PhpCsFixer:risky系列规则集的原因。CONFIGURABLE可配置规则规则通过assertions选项控制具体要修复哪些断言方法你可以只启用其中一部分。在源码中PhpUnitConstructFixer通过isRisky(): bool返回true来声明这一风险属性并在getDefinition()的第四个参数中写入与文档一致的风险说明参见 PhpUnitConstructFixer.php。配置项assertions详解取值与默认值规则仅有一个配置项assertions表示要修复的断言方法列表官方文档给出的约束如下允许值[assertEquals, assertNotEquals, assertNotSame, assertSame]的任意子集默认值上述四个方法全部启用。对应到源码配置定义位于createConfigurationDefinition()PhpUnitConstructFixer.php$assertMethods [ assertEquals, assertNotEquals, assertNotSame, assertSame, ]; return new FixerConfigurationResolver([ (new FixerOptionBuilder(assertions, List of assertion methods to fix.)) -setAllowedTypes([string[]]) -setAllowedValues([new AllowedValueSubset($assertMethods)]) -setDefault($assertMethods) -getOption(), ]);注意两点实现细节类型约束为string[]字符串数组取值校验使用AllowedValueSubset即允许传入完整列表的任意子集可以为空数组。当assertions为空数组时applyPhpUnitClassFix()会直接快速返回不执行任何修复。在配置文件中的启用方式启用该规则并自定义assertions的典型.php-cs-fixer.dist.php写法如下?php $finder PhpCsFixer\Finder::create() -in(__DIR__./tests); return (new PhpCsFixer\Config()) -setRules([ // 只修复 assertSame 与 assertNotSame 两种写法 php_unit_construct [assertions [assertSame, assertNotSame]], ]) -setFinder($finder);如果不写任何参数php_unit_construct true即表示四个方法全部启用。转换规则与映射表转换的两种方向源码中把四个可修复方法分成两组分别对应两套转换映射PhpUnitConstructFixer.php正向组fixAssertPositive用于assertSame与assertEquals原调用改写后assertSame(true, $foo)/assertEquals(true, $foo)assertTrue($foo)assertSame(false, $foo)/assertEquals(false, $foo)assertFalse($foo)assertSame(null, $foo)/assertEquals(null, $foo)assertNull($foo)负向组fixAssertNegative用于assertNotSame与assertNotEquals原调用改写后assertNotSame(true, $foo)/assertNotEquals(true, $foo)assertNotTrue($foo)assertNotSame(false, $foo)/assertNotEquals(false, $foo)assertNotFalse($foo)assertNotSame(null, $foo)/assertNotEquals(null, $foo)assertNotNull($foo)值得注意负向组在文档示例中展示的是assertNotSame(null, $d)→assertNotNull($d)而源码中true和false分别映射为assertNotTrue与assertNotFalse。换言之同一输入在被assertNotSame/assertNotEquals包裹时转换目标与assertSame/assertEquals方向相反但语义完全对应。匹配的前提条件fixAssert()方法PhpUnitConstructFixer.php在改写前会做三层安全检查缺一不可方法名 左括号的序列匹配通过Tokens::findSequence()在当前类作用域内寻找[T_STRING, $method]后紧跟(的调用点必须是同一类的调用使用FunctionsAnalyzer::isTheSameClassCall()确认该调用属于当前测试类典型即$this-assertXxx(...)。因此$sth-assertSame(true, $foo)这类其他对象上的调用不会被误改——这由测试用例[$sth-assertSame(true, $foo);]明确保证第一个参数必须是原生常量且调用确实是双参数形态第一个实参必须是true/false/null这类原生常量大小写不敏感TRUE、TruE、NULL均可识别测试中分别验证了assertEquals(FALSE, $foo)与assertEquals(TruE, $foo)的转换第一个参数之后必须是,说明存在第二个参数被断言的值。如果第一个参数后面直接是)说明是单参数调用不满足转换形态规则跳过。这些前置条件确保了规则只处理通用断言 字面量常量 双参数这一精确模式不会误伤assertSame($a, $b)两个变量比较或assertSame(true || $a, $b)第一个参数是表达式等场景——后者由测试用例[$this-assertSame(true || $a, $b); $this-assertTrue($c);]验证了其保持原样。官方示例默认配置与自定义配置示例一默认配置在默认配置四个方法全部启用下修复前后对比摘自官方文档?php final class FooTest extends \PHPUnit_Framework_TestCase { public function testSomething() { - $this-assertEquals(false, $b); - $this-assertSame(true, $a); - $this-assertNotEquals(null, $c); - $this-assertNotSame(null, $d); $this-assertFalse($b); $this-assertTrue($a); $this-assertNotNull($c); $this-assertNotNull($d); } }示例二自定义配置[assertions [assertSame, assertNotSame]]只启用assertSame与assertNotSame时assertEquals/assertNotEquals保持原样?php final class FooTest extends \PHPUnit_Framework_TestCase { public function testSomething() { $this-assertEquals(false, $b); - $this-assertSame(true, $a); $this-assertTrue($a); $this-assertNotEquals(null, $c); - $this-assertNotSame(null, $d); $this-assertNotNull($d); } }上述两个示例同时以CodeSample的形式固化在 Fixer 定义中PhpUnitConstructFixer.php并在测试基类tests/Fixer/PhpUnit/PhpUnitConstructFixerTest.php中被反复验证。规则的运行边界只在 PHPUnit 测试类内生效PhpUnitConstructFixer继承自AbstractPhpUnitFixer。后者通过PhpUnitTestCaseAnalyzer::findPhpUnitClasses()定位文件中的 PHPUnit 测试类并只在每个测试类的起止 token 区间内调用子类的applyPhpUnitClassFix()参见 AbstractPhpUnitFixer.php。因此该规则有以下隐式边界不在测试类中的断言调用不会被修改测试用例not in a class [?php $this-assertEquals(NULL, $foo);]与not phpunit class [?php class Foo { public function testFoo(){ $this-assertEquals(NULL, $foo); }}]明确验证了这一点判断是否为 PHPUnit 测试类的分析工作由PhpUnitTestCaseAnalyzer完成同时AbstractPhpUnitFixer也支持通过#[Test]属性PHPUnit\Framework\Attributes\Test识别的测试方法。与其他 PHPUnit 规则的配合顺序Fixer 通过getPriority()声明执行优先级PhpUnitConstructFixer.php/** * {inheritdoc} * * Must run before PhpUnitDedicateAssertFixer. */ public function getPriority(): int { return -8; }注释明确说明本规则必须在PhpUnitDedicateAssertFixer之前运行优先级数值为-8。这意味着先由php_unit_construct把assertSame(true, ...)这类调用改写成assertTrue(...)再交给后续的php_unit_dedicate_assert等规则继续处理避免两个规则在同一调用上产生冲突或重复改写。如果你的规则集同时启用了多个 PHPUnit 相关规则PHP-CS-Fixer 会自动按照优先级排序执行无需手动干预。所属规则集与启用方式官方文档列出该规则属于以下两个规则集PhpCsFixer:riskySymfony:risky在源码中php_unit_construct true直接出现在 SymfonyRiskySet.php而 PhpCsFixerRiskySet.php 通过Symfony:risky true间接引入该规则。因此最省事的启用方式是直接引入规则集return (new PhpCsFixer\Config()) -setRules([ Symfony:risky true, // 或 PhpCsFixer:risky true ]) -setFinder($finder);也可以单独启用并覆盖配置见上文配置文件中的启用方式。由于规则属于 risky 类别在使用--dry-run或 CI 检查时需要显式允许 risky 规则才能生效php php-cs-fixer fix --rules{php_unit_construct: true} --allow-riskyyes。风险提示与使用建议综合官方文档与源码使用php_unit_construct时需要注意覆写风险如果你的测试基类或被测对象覆写了 PHPUnit 的assertTrue/assertFalse/assertNull等原生方法并附加了断言之外的行为改写后的代码可能不再触发自定义实现。启用前建议用git grep检查项目内是否有同名方法覆写。行为等价性改写本身保持断言语义等价且仅针对第一个参数为true/false/null字面量、且为双参数调用的精确形态表达式、变量、单参数调用以及其他对象上的调用均不受影响均有测试用例背书。官方兼容性承诺PhpUnitConstructFixerTest中的每个测试用例都是官方向后兼容承诺的一部分文档 References 一节明确说明即规则的既有行为受测试保护升级 PHP-CS-Fixer 时不会被悄然改变。相关参考规则文档doc/rules/php_unit/php_unit_construct.rstFixer 实现src/Fixer/PhpUnit/PhpUnitConstructFixer.php测试用例tests/Fixer/PhpUnit/PhpUnitConstructFixerTest.php基类实现src/Fixer/AbstractPhpUnitFixer.php所属规则集doc/ruleSets/SymfonyRisky.rst 与 doc/ruleSets/PhpCsFixerRisky.rstPHPUnit 规则总览doc/rules/php_unit/index.rst赞分享开发工具代码质量静态分析Lint格式化【免费下载链接】PHP-CS-FixerA tool to automatically fix PHP Coding Standards issues项目地址https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer点击查看免费下载相关推荐PHP-CS-Fixer array_push 规则详解将 array_push($x, $y) 自动改写为 $x[] $yPHP CS Fixer array_push 规则详解将 array_push $x, $y 自动改写为 $x $y 导读 array_push 是 P开发工具代码质量静态分析Lint格式化PHP-CS-Fixer regular_callable_call 规则详解把 call_user_func* 调用改写成直接调用PHP CS Fixer regular_callable_call 规则详解把 call_user_func 调用改写成直接调用 导读 regular_ca开发工具代码质量静态分析Lint格式化终极指南如何在非越狱iOS设备上安装任意应用AltStore完整教程终极指南如何在非越狱iOS设备上安装任意应用AltStore完整教程 还在为iOS设备的封闭生态感到束手束脚吗想要突破App Store的限制安全地安装开发工具代码质量静态分析Lint格式化上一篇MyServer打造自己的本地服务器下一篇如何用树莓派Pico打造终极USB Rubber Ducky零基础5分钟上手教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
HCIA Datacom题库的正确用法:诊断知识盲区而非刷题 简介:本资源是华为HCIA-Datacom认证(H12-811)英语版官方题库PDF,专为备考该国际认证的网络工程师及高校通信/网络专业学生设计,聚焦OSI模型分层原理、VRP平台命令操作、TCP/IP协议栈解析、ARP地址映射机制、静态路由与… · 2026/9/23 15:30:13
Openclaw 语音控制实战:离线语音识别与云端 API 的配置骨架、性能与隐私对比 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/23 15:30:13
高效提升阅读效率的文献阅读神器 助力学术与专业文献快速解读吸收 刚接触一个新领域,最怕的就是迷失在海量的外国文献里,读了很多篇还是理不清脉络。我曾经也以为“研究现状”只能靠逐篇阅读、手动总结,直到发现了一些能生成“知识图谱”的神器。它们能让你像开了上帝视角一样,瞬间看清一个领域的… · 2026/9/23 16:13:25
屏幕亮度调节神器3种方案对比:面试必问的实战避坑指南 屏幕亮度调节神器3种方案对比:面试必问的实战避坑指南 刚学完 Python 语法,看着 print("Hello World") 都觉得顺眼,结果面试官问一句“怎么在 Linux… · 2026/9/23 16:13:25
数据怎么分析?实用分析方法与核心步骤全解析,带你快速掌握数据处理与价值挖掘逻辑 刚接触一个新领域,最怕的就是迷失在海量的外国文献里,读了很多篇还是理不清脉络。我曾经也以为“研究现状”只能靠逐篇阅读、手动总结,直到发现了一些能生成“知识图谱”的神器。它们能让你像开了上帝视角一样,瞬间看清一个领域的… · 2026/9/23 16:13:25
从SEO到GEO的范式迁移:原理、差异与工程实践 一、为什么会出现范式迁移
过去二十年,企业获取线上流量的核心方式是SEO(搜索引擎优化)——通过优化网页,让自己在搜索引擎结果页中排名更靠前。
但2024年以来,随着大语言模型(LLM)的爆发&#… · 2026/9/23 16:13:19
面试突击:音乐vip解析实战项目中的5个高频考点 面试突击:音乐vip解析实战项目中的5个高频考点 看了一堆教程还是不会写项目?这不仅是你的痛点,也是很多后端开发在面试“音乐资源解析”这类 实战项目 时栽跟头的地方。… · 2026/9/23 16:13:12
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29