如何为Groovy类中包含Shell脚本的方法编写单元测试
Jenkins共享库addTag方法单元测试实现思路
这是典型的Jenkins共享库测试场景,核心思路是通过模拟steps对象拦截所有sh调用,无需实际执行Shell和Git命令,仅验证代码逻辑正确性,具体实现步骤如下:
- 依赖引入:采用业界通用的
Jenkins Pipeline Unit测试框架搭配Spock测试框架实现,前者已经封装好了Jenkins流水线对象的模拟能力,后者是Groovy生态最常用的单元测试框架,二者适配性很高。 - 核心模拟逻辑:重写
steps.sh方法,捕获所有传入的脚本内容、参数,同时根据测试场景需要模拟Shell的返回值,不需要实际调用系统命令。 - 测试用例覆盖:
- 无历史版本Tag场景:模拟
git tag | grep "^[0-9].*" | tail -1返回空值,验证逻辑走入第一个分支,Git log命令不带历史Tag对比参数,且传入的tagName被正确拼接进git tag命令中。 - 存在历史版本Tag场景:模拟grep返回指定的历史Tag值(例如
1.0.0),验证逻辑走入第二个分支,Git log命令携带origin/$BRANCH_NAME...refs/tags/[历史Tag]对比参数,tagName拼接正确。 - 参数安全性测试:传入带特殊字符(空格、引号、$符)的tagName测试,可验证当前直接字符串拼接的写法是否存在Shell注入风险。
- 无历史版本Tag场景:模拟
- 断言逻辑实现:拦截到
sh的执行脚本后,直接校验脚本内容的分支逻辑、命令参数和预期一致即可,不需要真实执行Git操作。
参考测试代码示例(Spock)
import com.lesfurets.jenkins.unit.BasePipelineTest import spock.lang.Specification class AddTagTest extends Specification { BasePipelineTest pipelineTestHelper = new BasePipelineTest() def mockSteps def yourServiceInstance // 替换为你自己的Groovy类实例 def executedShScripts = [] def setup() { pipelineTestHelper.setUp() mockSteps = pipelineTestHelper.jenkinsRule.jenkins // 模拟sh方法,捕获所有执行的脚本 mockSteps.metaClass.sh = { Map params -> executedShScripts << params.script // 此处可根据测试场景自定义返回值 return 0 } // 实例化你的业务类,注入模拟的steps对象 yourServiceInstance = new YourBusinessClass(steps: mockSteps) } def "无历史Tag时逻辑分支正确"() { given: "配置模拟返回:Git查询不到符合规则的历史Tag" mockSteps.metaClass.sh = { Map params -> if(params.script.contains('git tag | grep "^[0-9]"')) { return "" // 模拟无历史Tag } return 0 } def testTagName = "2.0.0" when: "调用addTag方法" yourServiceInstance.addTag(testTagName) then: "验证Shell脚本逻辑符合预期" def targetScript = executedShScripts[0] // 校验走无Tag分支的Git log命令 targetScript.contains('git log origin/$BRANCH_NAME --pretty=format:"%h - %ce(%cn), %ar : %s"') // 校验Tag名称正确注入 targetScript.contains("git tag -a ${testTagName}") } def "存在历史Tag时逻辑分支正确"() { given: "配置模拟返回:存在历史Tag 1.0.0" mockSteps.metaClass.sh = { Map params -> if(params.script.contains('git tag | grep "^[0-9]"')) { return "1.0.0" // 模拟返回历史Tag } return 0 } def testTagName = "2.0.0" when: "调用addTag方法" yourServiceInstance.addTag(testTagName) then: "验证Shell脚本逻辑符合预期" def targetScript = executedShScripts[0] // 校验走有Tag分支的Git log对比命令 targetScript.contains('git log origin/$BRANCH_NAME...refs/tags/1.0.0 --pretty=format') targetScript.contains("git tag -a ${testTagName}") } }
注意:单元测试阶段不需要连接真实代码仓库、不需要执行真实Git命令,所有外部交互全部通过Mock模拟,仅验证你的代码逻辑、参数拼接正确性即可,真实功能验证可放到集成测试阶段执行。
内容的提问来源于stack exchange,提问作者Balaji Tendster
相关产品推荐
相关产品推荐

