ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Checkstyle 测试技术指南:TDD、输入文件结构与调试驱动的模块开发

Checkstyle 测试技术指南:TDD、输入文件结构与调试驱动的模块开发 Checkstyle 测试技术指南TDD、输入文件结构与调试驱动的模块开发【免费下载链接】checkstyleCheckstyle is a development tool to help programmers write Java code that adheres to a coding standard. By default it supports the Google Java Style Guide and Sun Code Conventions, but is highly configurable. It can be invoked with an ANT task and a command line program.项目地址: https://gitcode.com/GitHub_Trending/ch/checkstyleCheckstyle 的每一个 Check检查模块都配有体系化的单元测试它们不仅是回归保障更是模块开发的入口。本篇基于仓库 docs/TestingTechniques.md 系统讲解 Checkstyle 的测试组织方式、测试方法结构、输入文件Input File与行为驱动开发BDD的映射关系以及如何利用先写测试 调试器断点的 TDD 工作流精确分析并修复任意模块的问题。读完本文你将能独立定位测试代码与输入文件、读懂期望违规数组的格式并上手编写属于自己的模块测试。从 TDD 开始测试先行实现殿后TDDTest Driven Development测试驱动开发是 Checkstyle 社区鼓励的新功能实现方式。核心理念与经典 TDD 一致先写测试在实现功能之前先创建将验证该功能的测试。以测试为入口新建的测试方法充当通往模块源码的门。用调试器以 Debug 模式运行测试即可一步步复现模块的代码执行路径。以测试为实验场TDD 为模块的新实现提供了一个精确的实验环境你可以围绕该测试的结果持续迭代开发直到测试全部通过。对 Checkstyle 这种以静态分析为核心的项目而言TDD 的价值尤其明显每个 Check 的输入是 Java 源码输出是违规消息。先确定这段代码应当产生哪条违规再驱动实现去满足该预期比盲目实现后再补测试要高效得多。WhereCheckstyle 测试的位置与命名约定测试目录位于仓库的src/test/java/com/puppycrawl/tools/checkstyle/之下其后紧跟的是被测模块所在的相对路径。模块数据集合文件module data collection files测试按模块归集一个集合文件保存某个模块的全部测试。例如ArrayTypeStyleCheck数组类型风格检查的测试全部集中在src/test/java/com/puppycrawl/tools/checkstyle/checks/ArrayTypeStyleCheckTest.java。命名格式[ModuleClassName]Test其中[...]为你要填写的模块类名。即模块类FooCheck的测试类固定命名为FooCheckTest。除了单元测试仓库还维护了一套独立的集成测试IT目录src/it/java/例如org/checkstyle/base/AbstractCheckstyleModuleTestSupport.java、AbstractItModuleTestSupport.java用于在真实项目样本上验证模块行为可作为补充参考。测试结构一个 test 方法 一个独立用例模块数据集合文件中每个以test前缀命名的方法代表一个独立的测试。其通用骨架如下Test public void test[NameOfTest]() throws Exception { final String[] expected { ... } verifyWithInlineConfigParser( getPath(InputFile.java), expected); }仓库中的真实例子src/test/java/com/puppycrawl/tools/checkstyle/checks/ArrayTypeStyleCheckTest.java如下Test public void testJavaStyleOn() throws Exception { final String[] expected { 13:23: getCheckMessage(MSG_KEY), ... }; verifyWithInlineConfigParser( getPath(InputArrayTypeStyle.java), expected); }下面逐一拆解这个骨架的每个关键部分。1. 输入文件Input File被测对象输入文件是被测试的 Java 源文件它们位于与测试相同的src/test目录中但放在resources或resources-noncompilable文件夹下。JDK 21 分界规则当前 Checkstyle 以 JDK 21 作为基准运行版本。凡是能用 JDK 21或更早版本编译的输入文件放在src/test/resources/凡是需要更新版本 JDK 才能编译的如使用了更高版本 Java 语法特性则放进src/test/resources-noncompilable/。命名格式Input[ModuleName][FileNickname].java。例如为AnnotationLocation检查编写昵称为 Class 的输入文件应命名为InputAnnotationLocationClass.java。昵称虽然可以自由填写但建议与所属测试方法名相同或近似便于溯源对应关系。以ArrayTypeStyle模块为例仓库中的真实输入文件位于src/test/resources/com/puppycrawl/tools/checkstyle/checks/arraytypestyle/InputArrayTypeStyle.java其开头即内嵌模块配置/* ArrayTypeStyle javaStyle (default)true */ package com.puppycrawl.tools.checkstyle.checks.arraytypestyle; public class InputArrayTypeStyle { private int[] javaStyle new int[0]; ... }在测试中通过getPath(InputFile.java)定位输入文件。该方法在基类AbstractPathTestSupportsrc/test/java/com/puppycrawl/tools/checkstyle/AbstractPathTestSupport.java中实现new File(src/ getResourceLocation() /resources/ getPackageLocation() / filename).getCanonicalPath()即把资源目录根与包路径拼接成规范路径保证测试在不同工作目录下都能正确定位文件。2. 期望违规数组Expected Violations预期结果String[] expected数组存放测试期望收到的违规消息这些消息并不保证是模块当前实现实际输出的而是假设模块相关实现都正确生效后测试应当给出的结果。这正是 TDD 中红→绿→重构的判定依据实现正确前实际输出与 expected 不一致测试失败红实现正确后两者一致测试通过绿。每条元素的格式为lineNumber:columnNumber: 违规消息的其余部分其中违规消息的其余部分通常通过getCheckMessage(messageCode)生成。getCheckMessage会根据模块类所在包路径自动加载messages.properties中对应 messageCode 的文案因此测试写的是消息键而非硬编码文案这保证了多语言资源文件下测试依然成立。上例中的13:23: getCheckMessage(MSG_KEY)即表示期望在第 13 行第 23 列产生一条MSG_KEY对应的违规。3. 验证Verification实际与期望的比对输入文件与期望数组就绪后由验证方法通常是verifyWithInlineConfigParser()执行三步工作用 Checkstyle 分析输入文件收集当前实现实际检测到的违规将实际结果与expected逐一比对。若不一致测试失败并明确指出不一致发生在哪一行、哪一列、消息内容差异是什么。从源码看verifyWithInlineConfigParser(String filePath, String... expected)定义在测试基类src/test/java/com/puppycrawl/tools/checkstyle/AbstractModuleTestSupport.java中它先通过InlineConfigParser.parse(filePath)实现位于src/test/java/com/puppycrawl/tools/checkstyle/bdd/InlineConfigParser.java解析输入文件头部内嵌的配置块再据此构建 Checker 配置并执行校验。该基类还提供了多文件版本verifyWithInlineConfigParser(String filePath1, String filePath2, String... expected)、verifyWithInlineConfigParserSeparateConfigAndTarget配置与目标文件分离时使用以及面向日志输出的verifyWithInlineConfigParserAndDefaultLogger等重载满足多种测试场景。输入文件结构与 BDD把执行三阶段写进注释Checkstyle 输入文件遵循如下抽象结构/* ... config ... */ package [inputPathPackage] ... public class InputFileName { ... ... ... // violation, ... ... }这一结构体现了BDDBehavior Driven Development行为驱动开发思想它以直观的方式模拟执行的before执行前、during执行中、after执行后三种状态让开发者随时都能看清源码在每个执行阶段的状态。三个部分分别如下。ConfigBefore头部配置块输入文件开头用块注释/* ... */包裹的配置表示文件的before状态——它声明了模块运行于该代码之上所用的设置。配置有多种格式property属性、XML、java。常规测试一律使用property格式除非存在例外例如模块没有任何属性property 配置要求至少定义一个属性时改用XML格式。java格式是最后手段它需要在测试方法中额外定义配置、写在输入文件之外因而破坏了 BDD 的三态一目了然原则因此仅在其他格式都无法表达时才使用。property格式的布局如下/* ModuleName propertyName propertyValue otherPropertyName (default)otherPropertyDefaultValue ... lastPropertyName lastPropertyValue */其中(default)前缀表示该属性沿用默认值显式赋值则给出自定义值。仓库真实示例InputArrayTypeStyle.java的头部即为/* ArrayTypeStyle javaStyle (default)true */提示虽然示例未展示但强烈建议在配置末尾、闭合注释块之前保留 2 个空行。这样日后追加新属性时后续代码行号不会变化也就无需连带修改各违规标记与期望数组中的行号。Tested CodeDuring被测代码配置之后紧跟的 Java 源码即during状态。它是真正要被测试覆盖的代码片段也决定了本次测试的作用范围。BDD 的直观性在这里体现为测试人员无需跳转到别的文件即可在同一文件内看到用什么配置测什么代码。Violation MarkingAfter违规标记文件末尾部分以// violation注释标记测试的预期结果表示after状态——这些注释标在同一行预期产生违规的代码旁。标记格式为// violation, violation message其中违规消息必须属于该模块现有的某条违规消息即messages.properties中定义的某个 messageCode 对应的文案但引号内不必写全整条消息只需包含一部分即可作为匹配依据。综合三态可以看到BDD 让一个输入文件自描述为配置 A 作用于代码 B预期在 C、D 行产生违规这极大降低了测试的阅读理解成本也便于从 Issue 描述直接反推输入文件内容。调试驱动的模块分析断点 Debug 运行测试测试搭建完毕后它就成了一把分析模块的实时工具在模块源码即src/main/java/com/puppycrawl/tools/checkstyle/下对应 Check 类的任意位置打上断点以Debug模式运行对应的测试方法程序会在断点处暂停即可逐行观察模块在处理输入文件时的实际状态——包括语法树AST遍历位置、token 匹配情况、违规消息的拼接过程等。这种TDD 调试器的组合非常适合解决 GitHub Issues 中报告的具体模块问题Issue 通常已经给出输入文件样例与预期行为你只需据此创建输入文件与测试再用断点调试定位实现缺陷最后修复实现直至测试转绿。结论Checkstyle 的测试体系可以总结为一张清晰的链路位置测试类在src/test/java/...下按[ModuleClassName]Test命名输入文件在src/test/resources/可编译或src/test/resources-noncompilable/需更新 JDK下按Input[ModuleName][Nickname].java命名结构每个test前缀方法由输入文件、期望违规数组、验证调用三部分组成BDD输入文件头部的内嵌配置before、主体代码during与// violation标记after构成完整的执行三态工作流先写测试 → Debug 运行 → 断点观察 → 修复实现 → 测试转绿。掌握了这套方法论你就可以像 Checkstyle 维护者一样以测试为杠杆撬动对任何模块源码的精确理解与迭代。相关源码可从测试基类 AbstractModuleTestSupport.java、配置解析器 InlineConfigParser.java 以及真实用例 ArrayTypeStyleCheckTest.java 与 InputArrayTypeStyle.java 继续深入研读。【免费下载链接】checkstyleCheckstyle is a development tool to help programmers write Java code that adheres to a coding standard. By default it supports the Google Java Style Guide and Sun Code Conventions, but is highly configurable. It can be invoked with an ANT task and a command line program.项目地址: https://gitcode.com/GitHub_Trending/ch/checkstyle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表