尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

rubocop-github 测试驱动开发:用 Minitest 为自定义 Cop 编写单元测试

rubocop-github 测试驱动开发:用 Minitest 为自定义 Cop 编写单元测试 rubocop-github 测试驱动开发用 Minitest 为自定义 Cop 编写单元测试【免费下载链接】rubocop-githubCode style checking for GitHubs Ruby projects项目地址: https://gitcode.com/gh_mirrors/ru/rubocop-githubrubocop-github是 GitHub 官方维护的 Ruby 代码风格检查插件为 Ruby 项目提供了一套推荐配置和大量自定义 Cop检查规则。如果你想为它贡献新的检查规则或者想学习 RuboCop 插件开发的完整流程那么用 Minitest 编写单元测试是绕不开的一步。本文将用通俗易懂的方式带你从零开始为自定义 Cop 编写测试掌握测试驱动开发TDD的核心套路。为什么自定义 Cop 需要单元测试写代码风格检查插件最怕的是误报和漏报——该拦的没拦住不该拦的误伤一片。GitHub 团队深谙此道为rubocop-github里的每一个 Cop 都配了完整的 Minitest 测试。这些测试不仅仅是跑得通更是规则行为的契约每条 Cop 该抓什么、不该抓什么都被明明白白写进了测试里。更重要的是RuboCop 的 Cop 基于 AST抽象语法树匹配逻辑相当精巧一个小小的正则或节点匹配错误就可能影响成千上万个真实项目。单元测试是你修改 Cop 时最可靠的安全带。测试基础设施认识 CopTest 基类 打开test/cop_test.rb你会看到一个简洁但极其重要的基类CopTest。它只有两个核心方法investigate把一段 Ruby 源码交给指定的 Cop 检查返回所有违规offenseserb_investigate把一段 ERB 模板先编译成 Ruby 源码再检查专用于 View 类 Copdef investigate(cop, src, filename nil) processed_source RuboCop::ProcessedSource.new(src, RUBY_VERSION.to_f, filename) team RuboCop::Cop::Team.new([cop], cop.config, raise_error: true) report team.investigate(processed_source) report.offenses end这个基类帮你把构建源码→跑检查→取违规的流程封装好了你写测试时只需要关注输入什么代码、期望几个违规。第一步按命名规范创建测试文件 在test/目录下测试文件与 Cop 文件一一对应命名规则非常直观Cop 源码lib/rubocop/cop/github/insecure_hash_algorithm.rb测试文件test/test_insecure_hash_algorithm.rb每个测试文件的结构也高度统一require_relative cop_test require minitest/autorun require rubocop/cop/github/insecure_hash_algorithm class TestInsecureHashAlgorithm CopTest def cop_class RuboCop::Cop::GitHub::InsecureHashAlgorithm end # ...测试方法 end注意cop_class方法——它告诉基类要测试哪个 Cop所有测试方法都能通过cop访问到被测对象。测试类名使用Test Cop 名的驼峰形式测试方法一律以test_开头这是 Minitest 的约定。第二步编写该报错与不该报错的成对测试 ✅❌测试驱动开发的精髓在于同时验证正反两个方向。以test/test_avoid_object_send_with_dynamic_method.rb为例它测试的 Cop 是禁止用动态方法名调用senddef test_offended_by_send_call offenses investigate cop, -RUBY def my_method(foo) foo.send(some_ivar) end RUBY assert_equal 1, offenses.size end def test_unoffended_by_other_method_calls offenses investigate cop, -RUBY foo.bar(arg1, arg2) case some_ivar when :foo then baz.foo end RUBY assert_equal 0, offenses.size end测试的节奏非常清晰违规用例foo.send(some_ivar)传的是变量应该被判定为违规断言违规数为 1安全用例普通方法调用foo.bar不应该被误报断言违规数为 0除了数量还可以断言违规消息的精确内容确保文案也符合预期。比如test_insecure_hash_algorithm.rb中assert_equal #{cop.name}: #{cop_class::MSG}, offenses.first.message第三步测试带配置项的 Cop ⚙️很多 Cop 支持配置参数测试时不能只用默认配置。以InsecureHashAlgorithm为例它允许通过Allowed配置指定哪些哈希算法可以被豁免def make_cop(allowed:) config RuboCop::Config.new({ GitHub/InsecureHashAlgorithm { Allowed allowed } }) cop_class.new(config) end def test_uuid_v3_with_md5_allowed cop make_cop(allowed: %w[MD5]) offenses investigate(cop, -RUBY) Digest::UUID.uuid_v3(anything, anything) RUBY assert_equal 0, offenses.count end这是一个非常实用的测试模式先构造一个make_cop辅助方法再用不同的配置验证 Cop 的行为变化。比如配置只允许SHA512时SHA256就该报错配置允许SHA1时uuid_v5就不该报错——边界情况全都被覆盖到了。第四步为 View 相关 Cop 测试 ERB 模板 Rails 项目里很多代码写在 ERB 模板中普通源码检查无法直接处理。rubocop-github的解决方案是erb_investigate先把 ERB 编译成 Ruby再交给 Cop 检查。以test/test_rails_view_render_literal.rb为例def test_render_variable_offense offenses erb_investigate cop, -ERB, app/views/products/index.html.erb % render magic_string % % render partial: magic_string % ERB assert_equal 2, offenses.count end注意第二个参数传入了虚拟的文件名app/views/products/index.html.erb这能让 Cop 正确识别上下文也让测试更贴近真实场景。如果你想为 View 相关的 Cop 写测试直接复用这个模式即可。运行测试一键验证你的 Cop rubocop-github的测试运行非常简单两种方式任选bundle install bundle exec rake test或者直接执行项目自带的测试脚本script/testRakefile里已经配置好Rake::TestTask会自动发现test/目录下所有测试文件并运行。默认任务还会同时执行 RuboCop 对代码本身的检查确保你提交的代码风格也符合规范。测试驱动开发的最佳实践清单 结合rubocop-github的真实测试总结几条新手友好、可直接照搬的经验先写失败测试再写 Cop先用测试描述 Cop 应该有的行为看着它变红再实现 Cop 让它变绿这是 TDD 的标准节奏正反用例成对出现每个该抓的场景都配一个不该抓的场景防止过度匹配覆盖边界情况符号 vs 字符串、链式调用、带接收者 vs 不带接收者、命名空间常量test_unreliable_subclasses.rb里就有大量这样的边界用例断言消息内容不只断言违规数量还要校验违规消息防止文案漂移为配置项写独立用例Cop 有配置参数时单独构造配置并验证行为变化总结 ✨为自定义 Cop 写测试本质上就是回答三个问题它该抓什么它不该抓什么配置变化时行为怎么变借助test/cop_test.rb提供的基础设施和 Minitest 简洁的断言风格你完全可以用测试驱动的方式安全地开发、修改、重构自己的 RuboCop 插件。学会这套方法后rubocop-github里test/目录下的每一个测试文件都可以成为你学习 Cop 开发的活教材。【免费下载链接】rubocop-githubCode style checking for GitHubs Ruby projects项目地址: https://gitcode.com/gh_mirrors/ru/rubocop-github创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表