使用 Sourcery 的 LinuxMain 模板自动生成 LinuxMain.swift
代码生成开发工具【免费下载链接】SourceryMeta-programming for Swift, stop writing boilerplate code.项目地址https://gitcode.com/gh_mirrors/so/Sourcery点击查看免费下载导读在 Swift 工具链尚未普及测试自动发现test discovery的时期在 Linux 上运行 SwiftPM 测试需要手写LinuxMain.swift为每个XCTestCase子类补齐allTests静态数组并汇总到XCTMain。本指南围绕仓库官方文档 guides/LinuxMain.md 展开讲解如何借助 Sourcery 与内置的LinuxMain.stencil模板一次性为所有测试用例自动生成该文件读完本文你将掌握模板的触发方式、--args testimports参数、disableTests注解的使用以及模板在仓库中的源码实现与测试验证方式。为什么需要 LinuxMain.swiftLinuxMain.swift是 SwiftPM 在 Linux 平台上测试套件的统一入口文件。传统写法要求开发者手工完成两件事为每一个继承自XCTestCase的测试类声明静态allTests数组元素为(测试方法名, 方法引用)二元组在文件末尾将所有测试类的allTests通过testCase(...)包装后传给XCTMain([...])。当测试类数量增多、方法重命名或新增时手工维护这份清单极易遗漏或写错而 Sourcery 的 LinuxMain.stencil 模板正是为消除这一重复劳动而设计。模板的核心功能官方文档 guides/LinuxMain.md 明确了该模板的能力对全部测试用例生成allTests静态变量并把它们作为XCTestCaseEntry全部传入XCTMain。生成结果的形态如下文档原始示例import XCTest //testimports extension AutoInjectionTests { static var allTests [ (testThatItResolvesAutoInjectedDependencies, testThatItResolvesAutoInjectedDependencies), ... ] } extension AutoWiringTests { static var allTests [ (testThatItCanResolveWithAutoWiring, testThatItCanResolveWithAutoWiring), ... ] } ... XCTMain([ testCase(AutoInjectionTests.allTests), testCase(AutoWiringTests.allTests), ... ])需要注意仓库中实际模板生成的allTests声明带有完整的类型签名见 LinuxMain.stencilstatic var allTests: [(String, (AutoInjectionTests) - () throws - Void)] [...]这是 SwiftPM 在 Linux 上识别测试入口所要求的规范签名文档示例做了简化展示实际产出以模板为准。支持导入测试模块--args testimports若测试用例分散在多个模块中需要在生成文件顶部补充import语句。文档给出的运行方式是在命令行传入--args testimportsimport MyTests该值会被模板的{{ argument.testimports }}占位符原样输出对应 LinuxMain.stencil。例如sourcery --sources ./Tests --templates Templates/LinuxMain.stencil --output ./Tests/LinuxMain.swift --args testimportsimport MyTests从配置解析层面看args参数对应 Sourcery 配置中的args字典见 Sourcery/Configuration.swift 的public let args: [String: NSObject]定义在.sourcery.yml中可等价写成sources: - Tests templates: - Templates/LinuxMain.stencil output: Tests/LinuxMain.swift args: testimports: import MyTests多模块场景下可传入多行 import例如--args testimportsimport MyTests\nimport MyOtherTests。注解disableTests模板支持disableTests注解用于整体屏蔽某个测试类。在类声明上方添加// sourcery: disableTests class DisabledTests: XCTestCase { ... }模板在遍历时会跳过带该注解的类——既不会为其生成allTests扩展也不会将其加入XCTMain。仓库测试上下文 Templates/Tests/Context/LinuxMain.swift 中DisabledTests正是如此标注的可作为参考示例。模板源码逐段解读打开 LinuxMain.stencilStencil 语法可以完整还原它的生成逻辑import XCTest {{ argument.testimports }} {% for type in types.classes|based:XCTestCase %} {% if not type.annotations.disableTests %}extension {{ type.name }} { static var allTests: [(String, ({{ type.name }}) - () throws - Void)] [ {% for method in type.methods %}{% if method.parameters.count 0 and method.shortName|hasPrefix:test %} ({{ method.shortName }}, {{ method.shortName }}){{ , if not forloop.last }} {% endif %}{% endfor %}] } {% endif %}{% endfor %} // swiftlint:disable trailing_comma XCTMain([ {% for type in types.classes|based:XCTestCase %}{% if not type.annotations.disableTests %} testCase({{ type.name }}.allTests), {% endif %}{% endfor %}]) // swiftlint:enable trailing_comma关键点拆解types.classes|based:XCTestCasebased是 Sourcery 为 Stencil 注册的过滤器判断类型是否直接或间接继承自XCTestCase。其注册实现位于 SourceryStencil/Sources/StencilTemplate.swift对Type检查t.based[name] ! nil对Typed则下探到t.type?.based[name]。方法筛选条件只有parameters.count 0无参数且shortName以test前缀开头的方法才会进入allTests这与 XCTest 只把无参test开头方法当作测试用例的语义一致。disableTests过滤两处循环生成扩展、生成XCTMain条目都通过if not type.annotations.disableTests跳过被禁用类保证生成文件内部自洽。trailing comma 处理模板用// swiftlint:disable trailing_comma/enable包裹XCTMain数组避免生成的代码触发 SwiftLint 告警。仓库中的验证方式Sourcery 仓库自身就使用该模板并且通过测试确保模板输出稳定测试入口Templates/Tests/TemplatesTests.swift 中describe(LinuxMain template)用例调用check(template: LinuxMain)将实际生成结果与期望文件逐行比对忽略注释与首尾空白。输入上下文Templates/Tests/Context/LinuxMain.swift 定义了AutoInjectionTests、AutoWiringTests以及带disableTests注解的DisabledTestsLinux 专用变体见 Templates/Tests/Context_Linux/LinuxMain.swift。期望输出Templates/Tests/Expected/LinuxMain.expected 展示了DisabledTests被正确排除、剩余两个测试类各生成扩展并汇总进XCTMain的完整结果。实际生成Templates/Tests/Generated/LinuxMain.generated.swift 是测试运行时的产物Templates/Tests/TemplatesTests.swift 中generateFiles()通过sourcery --sources ... --templates ... --output ... --disableCache --verbose命令驱动生成这正是模板真实调用方式的可复现示例。从指南到落地使用步骤小结准备测试源码目录包含若干继承XCTestCase的类获取模板文件 LinuxMain.stencil可复制到自己的Templates/目录运行 Sourcerysourcery --sources ./Tests --templates ./Templates/LinuxMain.stencil --output ./Tests/LinuxMain.swift如测试分散在多个模块追加--args testimportsimport MyTests如需屏蔽个别测试类在类上方添加// sourcery: disableTests注解后重新生成。生成完成后将LinuxMain.swift纳入 SwiftPM 测试目标即可作为 Linux 测试入口使用仓库根目录的 LinuxMain.swift 本身即是由同类模板生成的产物可作为真实运行效果的参照。小结LinuxMain.stencil以“继承自 XCTestCase 的类 无参 test 前缀方法”为筛选规则自动产出符合 SwiftPM 规范的allTests与XCTMain入口并以disableTests注解提供细粒度豁免、以--args testimports支持多模块导入。配合仓库内 TemplatesTests.swift 的逐行比对测试模板的正确性得到了持续保障可以放心在自有项目中直接复用。赞分享代码生成开发工具【免费下载链接】SourceryMeta-programming for Swift, stop writing boilerplate code.项目地址https://gitcode.com/gh_mirrors/so/Sourcery点击查看免费下载相关推荐JTAppleCalendar代码生成框架使用Sourcery自动生成模板代码JTAppleCalendar代码生成框架使用Sourcery自动生成模板代码 你是否还在为JTAppleCalendar中重复编写相似的日历单元格和头部视图移动开发UI组件MJRefresh 与代码生成使用 Sourcery 自动生成刷新逻辑MJRefresh 与代码生成使用 Sourcery 自动生成刷新逻辑 你是否还在手动编写重复的下拉刷新和上拉加载代码每次修改刷新样式都要逐个修改控制器本移动开发UI组件终极指南如何用Sourcery自动生成async/await样板代码终极指南如何用Sourcery自动生成async/await样板代码 Swift的async/await语法让异步编程变得简单优雅但随之而来的是大量的样板代代码生成开发工具上一篇LZHAM常见问题解答从错误处理到性能瓶颈突破下一篇为什么Refactorator是Swift开发者必备工具5大核心功能深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考