You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins流水线中Katalon失败用例截图存储及Jira工单创建求助

问题解决方案

1. Katalon捕获失败测试用例截图并同步到Jenkins(含查看方法)

核心思路

利用Katalon的Test Listener实现全局失败自动截图,将截图保存到Jenkins工作空间,再通过Jenkins的工件归档功能查看。

步骤1:获取Jenkins工作空间路径

Jenkins运行时会自动设置WORKSPACE环境变量,在Katalon中直接通过代码获取:

def jenkinsWorkspace = System.getenv("WORKSPACE") ?: System.getProperty("user.dir")

如果本地运行测试(非Jenkins环境),会自动 fallback 到Katalon项目根目录,保证兼容性。

步骤2:编写全局失败监听类

创建Test Listener(右键Test Listeners -> New -> Test Listener),在onTestFailure方法中实现截图逻辑:

import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.testlistener.TestListenerAdapter
import java.nio.file.Files
import java.nio.file.Paths

class FailureScreenshotListener extends TestListenerAdapter {
    @Override
    void onTestFailure(TestCaseContext testCaseContext) {
        // 定义截图保存目录(Jenkins工作空间下的screenshots文件夹)
        def screenshotDir = Paths.get(System.getenv("WORKSPACE") ?: System.getProperty("user.dir"), "screenshots")
        // 自动创建目录(如果不存在)
        if (!Files.exists(screenshotDir)) {
            Files.createDirectories(screenshotDir)
        }
        // 生成唯一截图文件名(用例ID+时间戳,避免重名)
        def screenshotPath = screenshotDir.resolve("${testCaseContext.getTestCaseId()}_${new Date().format('yyyyMMdd_HHmmss')}.png").toString()
        
        try {
            // 捕获截图并添加到Katalon测试报告
            WebUI.takeScreenshot(screenshotPath)
            testCaseContext.addAttachment(screenshotPath)
        } catch (Exception e) {
            println("截图失败: " + e.getMessage())
        }
    }
}

步骤3:Jenkins配置与截图查看

  • 构建后操作中添加Archive the artifacts,设置归档文件规则为screenshots/**
  • 构建完成后,在Jenkins的构建详情页点击Artifacts链接,即可进入screenshots文件夹查看所有失败截图
  • 同时Katalon生成的HTML测试报告会自动包含截图附件,在Jenkins中打开报告也能直接查看对应失败用例的截图

2. 测试失败时自动在Jira创建工单(附截图与失败信息)

核心思路

通过Jira REST API创建工单,再上传截图作为附件,逻辑同样集成在Test Listener中,实现全局自动触发。

步骤1:准备Jira凭证

  • 登录Jira个人账号,生成API Token(路径:个人设置 -> Security -> API tokens)
  • 记录以下信息:Jira域名、你的登录邮箱、API Token、目标项目Key

步骤2:扩展Test Listener的失败逻辑

在之前的FailureScreenshotListener类中,添加Jira工单创建与附件上传代码:

import groovy.json.JsonBuilder
import groovyx.net.http.RESTClient
import static groovyx.net.http.ContentType.JSON

// ... 保留之前的截图逻辑代码 ...

@Override
void onTestFailure(TestCaseContext testCaseContext) {
    // --- 先执行截图逻辑(同之前代码)---
    def workspacePath = System.getenv("WORKSPACE") ?: System.getProperty("user.dir")
    def screenshotDir = Paths.get(workspacePath, "screenshots")
    if (!Files.exists(screenshotDir)) Files.createDirectories(screenshotDir)
    def screenshotPath = screenshotDir.resolve("${testCaseContext.getTestCaseId()}_${new Date().format('yyyyMMdd_HHmmss')}.png").toString()
    try {
        WebUI.takeScreenshot(screenshotPath)
        testCaseContext.addAttachment(screenshotPath)
    } catch (Exception e) {
        println("截图失败: " + e.getMessage())
    }

    // --- 开始Jira工单创建逻辑 ---
    def jiraConfig = [
        domain: "https://your-jira-domain.atlassian.net",
        username: "your-email@example.com",
        apiToken: "your-api-token",
        projectKey: "PROJ", // 替换为你的Jira项目Key
        issueType: "Bug" // 替换为你要创建的工单类型,比如Bug/Task
    ]

    // 构造工单内容
    def summary = "测试用例失败: ${testCaseContext.getTestCaseId()}"
    def errorMsg = testCaseContext.getTestCaseStatus().getErrorMessages().join("\n")
    def description = """
**测试用例ID**: ${testCaseContext.getTestCaseId()}
**失败时间**: ${new Date().format('yyyy-MM-dd HH:mm:ss')}
**错误信息**:
${errorMsg}
"""

    try {
        // 创建Jira REST客户端
        def client = new RESTClient(jiraConfig.domain)
        client.auth.basic(jiraConfig.username, jiraConfig.apiToken)

        // 发送创建工单请求
        def issueRequest = new JsonBuilder([
            fields: [
                project: [key: jiraConfig.projectKey],
                summary: summary,
                description: [
                    type: "doc",
                    version: 1,
                    content: [
                        [
                            type: "paragraph",
                            content: [[type: "text", text: description]]
                        ]
                    ]
                ],
                issuetype: [name: jiraConfig.issueType]
            ]
        ])

        def createResponse = client.post(
            path: "/rest/api/3/issue",
            body: issueRequest.toString(),
            contentType: JSON
        )

        def issueKey = createResponse.data.key
        println("已创建Jira工单: ${issueKey}")

        // 上传截图到工单
        if (Files.exists(Paths.get(screenshotPath))) {
            client.post(
                path: "/rest/api/3/issue/${issueKey}/attachments",
                body: [file: new File(screenshotPath)],
                requestContentType: "multipart/form-data"
            )
            println("截图已附加到工单 ${issueKey}")
        }
    } catch (Exception e) {
        println("Jira工单创建失败: " + e.getMessage())
    }
}

步骤3:添加依赖

Katalon默认没有集成groovy HTTP客户端,需要手动添加:

  1. 下载与Katalon内置Groovy版本兼容的groovy-all.jar(推荐2.5.x版本)
  2. 将jar包放到Katalon项目的Drivers文件夹,右键选择Add as external library

注意事项

  • 确保Jenkins服务器能正常访问你的Jira域名
  • 建议将Jira配置信息放到Katalon全局变量中,避免硬编码
  • 保留异常捕获逻辑,防止Jira请求失败导致测试流程中断

内容的提问来源于stack exchange,提问作者ninakeller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 18:46:16