Junit4遇上chatGPT

京东云开发者
• 阅读 164

这是一篇适合Java工程师体质的AI开发教程。

本教程会教你写一个简单的junit4的Rule,该Rule在基于junit4的测试方法失败后,自动向GPT发送错误信息并通过GPT分析得出代码修改建议。

首先向AI问好

简单的通过AI,让它基于json格式生成相应的类文件,这样方便我们在代码中使用,而不用显示写json字符串。

package com.jd.jr.parrot.llm;

import lombok.Data;

/**
 * created on 2023/7/25 20:07
 *
 * @author Dragonchu
 */
@Data
public class Choice {
    private String finish_reason;
    private int index;
    private Message message;
}
package com.jd.jr.parrot.llm;

import lombok.Data;

/**
 * created on 2023/7/25 20:07
 *
 * @author Dragonchu
 */
@Data
public class Message {
    private String role;
    private String content;
}
package com.jd.jr.parrot.llm;

import lombok.Data;

/**
 * created on 2023/7/25 20:06
 *
 * @author Dragonchu
 */
@Data
public class Usage {
    private int completion_tokens;
    private int prompt_tokens;
    private int total_tokens;
}
package com.jd.jr.parrot.llm;

import java.util.List;
import lombok.Data;

/**
 * created on 2023/7/25 20:17
 *
 * @author Dragonchu
 */
@Data
public class OpenAiRequest {
    private String erp;
    private List<Message> messages;
    private String model;
}
package com.jd.jr.parrot.llm;

import java.util.List;
import lombok.Data;

/**
 * created on 2023/7/25 20:04
 *
 * @author Dragonchu
 */
@Data
public class OpenAiResponse {
    private long created;
    private Usage usage;
    private String model;
    private String id;
    private List<Choice> choices;
    private String object;
}

封装一个简单的工具,以供使用GPT

package com.jd.jr.parrot.llm;

import com.google.gson.Gson;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * created on 2023/7/25 20:07
 *
 * @author Dragonchu
 */
@Slf4j
public class LLMUtil {
    private static String url = "Your url";
    private static String apiKey = "Your key";

    public static String sendMsg(String msg){
        OpenAiRequest request = new OpenAiRequest();
        Message message = new Message();
        message.setRole("user");
        message.setContent(msg);
        request.setMessages(Arrays.asList(message));
        request.setModel("gpt-3.5-turbo");
        Gson gson = new Gson();
        String result = postGPT(url, gson.toJson(request));
        OpenAiResponse openAiResponse = gson.fromJson(result, OpenAiResponse.class);
        return openAiResponse.getChoices().get(0).getMessage().getContent();
    }

    /**
     * 发送 post 请求
     *
     * @param url     请求地址
     * @param jsonStr Form表单json字符串
     * @return 请求结果
     */
    public static String postGPT(String url, String jsonStr) {
        // 创建httpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 创建post请求方式实例
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-type", "application/json;charset=utf-8");
        httpPost.setHeader("Authorization", apiKey);

        // 设置参数---设置消息实体 也就是携带的数据
        StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
        // 设置编码格式
        entity.setContentEncoding("UTF-8");
        // 发送Json格式的数据请求
        entity.setContentType("application/json");
        // 把请求消息实体塞进去
        httpPost.setEntity(entity);
        // 执行http的post请求
        CloseableHttpResponse httpResponse;
        String result = null;
        try {
            httpResponse = httpClient.execute(httpPost);
            result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
            if (httpResponse.getStatusLine().getStatusCode() != 200) {
                System.out.println("post->return error,result: " + result);
                log.error("post->return error,result: {}", result);
            }
        } catch (IOException e) {
            log.error("postStream->error", e);
            e.printStackTrace();
        }
        return result;
    }

    public static void main(String[] args) {
        log.info(sendMsg("Who are you?"));
    }

}



Junit4遇上chatGPT



然后写一个Watcher

junit4提供了Rule机制,该机制利用AOP,使得我们可以在测试代码中嵌入相应的逻辑,比如在执行代码前输出方法名,捕获异常等。TestWatcher是一个抽象类,通过覆盖该类我们可以得到一个满足我们需求的Rule。

我们希望能在测试方法失败抛出异常后,直接将异常信息和异常堆栈发送给GPT,同时,也要将出错的代码文件发送给GPT(注意敏感信息哦,本文只是一个教程,请勿私自将敏感代码发送给GPT)。

简单写一个工具类,这个类封装了从异常堆栈中获取文件的能力。

package com.jd.jr.parrot;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * created on 2023/7/28 15:08
 *
 * @author Dragonchu
 */
public class ExceptionUtil {
    public static String getFileName(String stackTraceLine) {
        // 使用正则表达式提取文件名
        Pattern pattern = Pattern.compile("\((.*\.java)");
        Matcher matcher = pattern.matcher(stackTraceLine);
        if (matcher.find()) {
            String fileName = matcher.group(1);
            return fileName;
        }
        return null;
    }

    public static Path getPath(String stackTraceLine) {

        // 提取文件路径
        int firstParenthesisIndex = stackTraceLine.indexOf("(");
        int firstDotIndex = stackTraceLine.lastIndexOf(".", firstParenthesisIndex);
        String packagePath = stackTraceLine.substring(0, firstDotIndex).replace(".", File.separator);
        // 获取根路径
        String rootPath = new File("").getAbsolutePath();

        Path filePath = Paths.get(rootPath, "src", "main", "java", packagePath + ".java");
        return filePath;
    }

    public static String getCodeFile(String stackTraceLine) {
        Path filePath = getPath(stackTraceLine);
        if (filePath.toFile().exists()) {
            // 读取文件内容
            try (BufferedReader reader = new BufferedReader(new FileReader(filePath.toFile()))) {
                StringBuilder content = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    content.append(line).append("\n");
                }
                return content.toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static void main(String[] args) {
        String stackTraceLine = "com.jd.jr.parrot.ExceptionExample.main(ExceptionExample.java:24)";
        String fileName = getFileName(stackTraceLine);
        System.out.println("fileName = " + fileName);
        String path = getPath(stackTraceLine).toString();
        System.out.println("path = " + path);
        String codeFile = getCodeFile(stackTraceLine);
        System.out.println("codeFile = " + codeFile);
    }
}

简单地设计一个prompt,也就是我们需要发给GPT的信息。

private static final String prompt = ""You are a good Java engineer, please analyze the following error and provide possible solutions." +
    "The error message is : %s, The error stack is : %s. The code file is : %s";

当测试方法抛出异常后,我们将异常相关信息以及代码文件发送给GPT让它进行分析。

package com.jd.jr.parrot.junit;

import com.jd.jr.parrot.ExceptionUtil;
import com.jd.jr.parrot.llm.LLMUtil;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

/**
 * created on 2023/7/28 14:07
 *
 * @author Dragonchu
 */
@Slf4j
public class OverWatch extends TestWatcher {

    private static final String prompt = ""You are a good Java engineer, please analyze the following error and provide possible solutions." +
        "The error message is : %s, The error stack is : %s. The code file is : %s";

    @Override
    protected void failed(Throwable e, Description description) {
        super.failed(e, description);
        String codeFile = ExceptionUtil.getCodeFile(e.getStackTrace()[0].toString());
        log.info(LLMUtil.sendMsg(String.format(prompt, e.getMessage(), Arrays.toString(e.getStackTrace()),codeFile)));
    }
}

让AI给我一份错误代码

本着能不自己干就不自己干的态度,我们让AI生成一份有错误的代码。

这是我与AI的对话:

我:

给我一份会抛出异常的代码,我希望这份代码稍微复杂一点,且依赖了一些外部包,它错误的原因比较难以排查。

AI:

以下是一个稍微复杂一点且依赖外部包的会抛出异常的Java代码示例:

📎importorg.jsoup.Jsoup;importorg.jsoup.nodes.Document;importorg.jsoup.nodes.Element;importorg.jsoup.select.Elements;importjava.io.IOException;publicclassExceptionExample{    publicstaticvoidmain(String[]args){        try{            // 使用Jsoup抓取网页内容            Documentdoc=Jsoup.connect("https://www.example.com").get();                        // 解析网页内容            Elementtitle=doc.select("title").first();            System.out.println("Title: "+title.text());                        // 尝试获取一个不存在的元素            ElementnonExistentElement=doc.select("#nonexistent-element").first();                        // 在非空元素上调用方法,会抛出NullPointerException            nonExistentElement.text();                    }catch(IOExceptione){            e.printStackTrace();        }    }}

这段代码使用外部包Jsoup来抓取网页内容并解析,然后尝试获取一个不存在的元素并在其上调用方法,会抛出NullPointerException异常。该异常可能比较难以排查,需要检查代码是否正确处理了异常情况,以及是否正确使用外部包的API等。



测试,让AI在junit测试失败后分析代码

简单写一个测试:

package com.jd.jr.parrot;

import com.jd.jr.parrot.junit.OverWatch;
import java.io.IOException;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runners.MethodSorters;

/**
 * created on 2023/7/28 14:14
 *
 * @author Dragonchu
 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OverWatchTest {
    @Rule
    public OverWatch overWatch = new OverWatch();

    @Test
    public void jsoupTest() throws IOException {
        ExceptionExample.main(new String[]{});
    }
}

测试结果



Junit4遇上chatGPT

作者:京东科技 储惠龙

来源:京东云开发者社区

点赞
收藏
评论区
推荐文章
不是海碗 不是海碗
1年前
ChatGPT 到底强大在哪里?(文末有彩蛋)
ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序,于2022年11月推出。该程序使用基于GPT3.5架构的大型语言模型并通过强化学习进行训练。ChatGPT以文字方式交互,而除了可以通过人类自然对话方式进行交互,还可以用于相对复杂的语言工作,包括自动文本生成、自动问答、自动摘要等在内的多种任务。
不是海碗 不是海碗
1年前
不要慌,我们谈一谈如何用好 ChatGPT
ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序,于2022年11月推出。该程序使用基于GPT3.5架构的大型语言模型并通过强化学习进行训练。ChatGPT以文字方式交互,而除了可以通过人类自然对话方式进行交互,还可以用于相对复杂的语言工作,包括自动文本生成、自动问答、自动摘要等在内的多种任务。
不是海碗 不是海碗
1年前
超火的 ChatGPT,APISpace 让你一分钟免费接入
ChatGPT是一个基于GPT3.5(GenerativePretrainedTransformer3.5)的语言模型,用于处理自然语言问答。GPT3.5是由人工智能公司OpenAI开发的一种大型神经网络模型,能够处理自然语言文本。ChatGPT是基于GPT3.5模型构建的,能够根据用户输入的问题,生成自然语言的回答。
不是海碗 不是海碗
1年前
一文带你了解 chatgpt
ChatGPT是一款由OpenAl开发的语言模型产品,它能够模拟人类的语言行为,与用户进行自然的交互。ChatGPT基于GPT3.5(GenerativePretrainedTransformer3.5)的语言模型建造,通过使用大量的训练数据来模拟人类的语言行为,并通过语法和语义分析,生成人类可以理解的文本。
Wesley13 Wesley13
3年前
Java基础学习总结(24)——Java单元测试之JUnit4详解
Java单元测试之JUnit4详解与JUnit3不同,JUnit4通过注解的方式来识别测试方法。目前支持的主要注解有:@BeforeClass 全局只会执行一次,而且是第一个运行@Before 在测试方法运行之前运行@Test(http://my.oschina.net/azibug) 测试方法
基于AIGC的京东购物助手的技术方案设想 | 京东云技术团队
随着AIGC的爆火,ChatGPT,GPT4的发布,我作为一个算法工作者,深感AI发展的迅猛。最近,OpenAI的插件和联网功能陆续向用户公开,我也在第一时间试用了这些最新的功能。在OpenAI的插件市场上,我被一个可以帮助分析食谱,并生成购物清单的功能所吸引。
ChatGPT风口下的技术“狂飙”,天翼云荣登ZeroCLUE榜首
最近ChatGPT火了!写代码、写情书、写文章、做题……它啥都会。在ChatGPT强大的功能背后,离不开业内不断精进的人工智能技术的支撑。零样本学习就是ChatGPT的核心技术之一。近日,智能边缘事业部AI团队在中文语言理解零样本学习权威榜单ZeroCLU
花母 花母
1年前
ChatGPT 横空出世,大模型全面赋能,分享国内可用的ChatGPT小程序
ChatGPT作为一种新的Ai聊天机器人,能够满足用户多元化场景。如:Ai聊天、自动写文案、写代码、写论文、文案翻译、成为老师、翻译官等等第一步:关注公众号:智星AI小助手智星AI小助手采用大数据模型gpt能力,它可以完成所有各类场景对话,包括但不限于与