返回顶部
首页 > 资讯 > 后端开发 > GO >Golang怎么使用ChatGPT生成单元测试
  • 162
分享到

Golang怎么使用ChatGPT生成单元测试

2023-07-05 13:07:27 162人浏览 泡泡鱼
摘要

这篇文章主要介绍“golang怎么使用ChatGPT生成单元测试”,在日常操作中,相信很多人在Golang怎么使用ChatGPT生成单元测试问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang怎么使用C

这篇文章主要介绍“golang怎么使用ChatGPT生成单元测试”,在日常操作中,相信很多人在Golang怎么使用ChatGPT生成单元测试问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang怎么使用ChatGPT生成单元测试”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

生成单元测试的工作流如下:

  • 选定你的待测函数

  • 分析函数的依赖:结构体定义、repo依赖、repo interface抽象(用fx和wire框架依赖注入的话会方便很多)

  • 组织prompt,准备施法

  • 吟唱魔法,得到输出单元测试代码

  • copy到ide里面缝缝补补,与预期出入太多的话,调整prompt重来/要求gpt按照某个标准重写(比如:请按照testCases的写法重写组织测试数据)

  • 运行测试用例

Part1 easy:单个函数,无复杂依赖

单个函数,并且外部依赖都是开源库,那么直接把代码贴上去就行。

这里我们用图片压缩的独立函数举例: (prompt前摇咒语 + 代码片段)

写下列代码中CompressPicture函数的单测,要求覆盖全部逻辑。断言使用require包。测试用例以testCases的形式输出。// CompressPicture the picture by resizing it to the specified width.func CompressPicture(picData []byte, width uint) ([]byte, error) {   // Decode the input image.   oldBuffer := bytes.NewBuffer(picData)   inputImg, _, err := image.Decode(oldBuffer)   if err != nil {      return nil, err   }   // Resize the image to the specified width.   outputImg := resize.Resize(width, 0, inputImg, resize.Lanczos3)   // Encode the output image as PNG and write it to a buffer.   newBuffer := new(bytes.Buffer)   err = png.Encode(newBuffer, outputImg)   if err != nil {      return nil, err   }   // Return the compressed image as a byte slice.   return newBuffer.Bytes(), nil}

ChatGPT输出的代码块如下:

func TestCompressPicture(t *testing.T) {   // Setup test data   imgData, err := os.ReadFile("test-image.png")   if err != nil {      t.Fatalf("failed to read test image file: %v", err)   }   testCases := []struct {      name  string      width uint   }{      {"compress with a valid width", 500},      {"compress with an invalid width", 0},   }   for _, tc := range testCases {      t.Run(tc.name, func(t *testing.T) {         // Invoke the function being tested.         compressedData, err := CompressPicture(imgData, tc.width)         // Check the result.         if err != nil {            t.Fatalf("unexpected error: %v", err)         }         if len(compressedData) == 0 {            t.Fatalf("compressed data is empty")         }         create, err := os.Create("test-image-compressed.png")         if err != nil {            return         }         defer create.Close()         _, err = create.Write(compressedData)      })   }}

放到ide里,完美运行,说明简单函数的单元测试生成还是很强的~

Golang怎么使用ChatGPT生成单元测试

Part2 nORMal :里面有一些外部import

有外部定义引入的时候,最好把外部定义直接贴上(不涉及mock)。

这里举例的函数出现了外部依赖 entity.ArcHiveWithData等定义,所以最好要加上外部定义在输入中:

写下列代码中ConvertArchiveWithDataToBotTextMsg函数的单测,要求覆盖全部逻辑。断言使用require包。测试用例以testCases的形式输出。// ConvertArchiveWithDataToBotTextMsg 将画作稿件信息转换为企微机器人文本消息func ConvertArchiveWithDataToBotTextMsg(data *entity.ArchiveWithData) *entity.BotMsgReq {   var MentionedList []string   proxyUrl := data.Info.Urls.Original   rawPixivUrl := fmt.Sprintf("https://www.pixiv.net/artworks/%d", data.Info.Pid)   txt := &entity.BotText{      Content:       fmt.Sprintf("proxy图源:%s\npixiv图源:%s", proxyUrl, rawPixivUrl),      MentionedList: MentionedList,   }   postText := &entity.BotMsgReq{      MsgType: entity.BotMsgText,      Text:    txt,   }   return postText}一些导入的定义如下:type BotText struct {   Content       string   `JSON:"content"`   MentionedList []string `json:"mentioned_list"`}type BotMsgReq struct {   MsgType BotMsgType `json:"msgtype"`   Text    *BotText   `json:"text,omitempty"`}const (   BotMsgText  BotMsgType = "text")type ArchiveWithData struct {   Info Archive   Data []byte}

下面是生成的代码,经过少量修改后可以直接运行:(因为少输入了一个结构体的定义,导致它猜测了一些字段)

func Test_ConvertArchiveWithDataToBotTextMsg(t *testing.T) {   testCases := []struct {      name     string      data     *entity.ArchiveWithData      expected *entity.BotMsgReq   }{      {         name: "regular data",         data: &entity.ArchiveWithData{            Info: entity.Archive{               Pid: 123456,               Urls: entity.PicUrl{                  Original: "Https://example.com/image.jpg",               },            },            Data: []byte{},         },         expected: &entity.BotMsgReq{            MsgType: entity.BotMsgText,            Text: &entity.BotText{               Content: "proxy图源:https://example.com/image.jpg\npixiv图源:https://www.pixiv.net/artworks/123456",            },         },      },      {         name: "data with special characters",         data: &entity.ArchiveWithData{            Info: entity.Archive{               Pid: 789012,               Urls: entity.PicUrl{                  Original: "https://example.com/image(with)special&characters.jpg",               },            },            Data: []byte{},         },         expected: &entity.BotMsgReq{            MsgType: entity.BotMsgText,            Text: &entity.BotText{               Content: "proxy图源:https://example.com/image(with)special&characters.jpg\npixiv图源:https://www.pixiv.net/artworks/789012",            },         },      },   }   for _, tc := range testCases {      t.Run(tc.name, func(t *testing.T) {         result := ConvertArchiveWithDataToBotTextMsg(tc.data)         require.Equal(t, tc.expected, result)      })   }}

Golang怎么使用ChatGPT生成单元测试

Part3 hard:对外部repo进行mock(gomock举例)

外部依赖越多,prompt template的构建可能就越复杂

ps.实际上gomonkey它也可以写

外部依赖repo的部分,要求gpt使用gomock进行对应repo的mock即可。

外部定义最好进行剪枝。

输入:

写下列代码中getSeTuDescSlice函数的单测,要求覆盖全部逻辑。断言使用require包。测试用例以testCases的形式输出。对于m.repoSeTu.GetArchiveInfoSlice的调用,使用gomock进行mock处理,假设已经有mock文件。func (m *CronTab) getSeTuDescSlice(ctx context.Context, seTuConfig config.SeTuConfig) (entity.QueryResult, error) {   queryResSlice, err := m.repoSeTu.GetArchiveInfoSlice(ctx, &entity.Query{      R18:   seTuConfig.R18,      Num:   1,      Tag:   seTuConfig.Tags,      Size:  seTuConfig.PicSize,      Proxy: seTuConfig.Proxy,   })   if err != nil {      return entity.QueryResult{}, err   }   return queryResSlice, nil}下面是外部依赖的定义:type SeTuConfig struct {   SetuapiUrl string   `yaml:"setu_api_url"`   QWAuth     []string `yaml:"qw_auth"`   CronStr    string   `yaml:"cron_str"`   R18        int64    `yaml:"r_18"`   Tags       []string `yaml:"tags"`   PicSize    []string `yaml:"pic_size"`   Proxy      string   `yaml:"proxy"`}// QueryResult 请求结果type QueryResult struct {   Error        string    `json:"error"`   ArchiveSlice []Archive `json:"data"`   //picPaths     []string}

输出:

假设已经有mock文件:// mock_repoSetu 是通过mockgen自动生成的,用于模拟repoSetu接口的mock文件func TestCronTab_getSeTuDescSlice(t *testing.T) {    testCases := []struct{        name string        seTuConfig config.SeTuConfig        getArchiveInfoSliceRes entity.QueryResult        getArchiveInfoSliceErr error        wantErr bool    }{        {            name: "success",            seTuConfig: config.SeTuConfig{                R18: 0,                Tags: []string{"tag1", "tag2"},                PicSize: []string{"large"},                Proxy: "",            },            getArchiveInfoSliceRes: entity.QueryResult{                ArchiveSlice: []entity.Archive{                    {                        Urls: []string{"pic1.url", "pic2.url"},                        Title: "pic1",                        Artists: []string{"artist1"},                    },                },            },            getArchiveInfoSliceErr: nil,            wantErr: false,        },        {            name: "error",            seTuConfig: config.SeTuConfig{                R18: 1,                Tags: []string{"tag3"},                PicSize: []string{"small", "medium"},                Proxy: "",            },            getArchiveInfoSliceRes: entity.QueryResult{},            getArchiveInfoSliceErr: errors.New("get archive info slice error"),            wantErr: true,        },    }    for _, tc := range testCases {        t.Run(tc.name, func(t *testing.T) {            ctx := context.Background()            // 创建mock对象            mockRepoSeTu := mock_repoSetu.NewMockRepoSeTu(ctrl)            m := &CronTab{repoSeTu: mockRepoSeTu}            // 设置mock对象返回值            mockRepoSeTu.EXPECT().GetArchiveInfoSlice(ctx, &entity.Query{                R18: tc.seTuConfig.R18,                Num: 1,                Tag: tc.seTuConfig.Tags,                Size: tc.seTuConfig.PicSize,                Proxy: tc.seTuConfig.Proxy,            }).Return(tc.getArchiveInfoSliceRes, tc.getArchiveInfoSliceErr)            res, err := m.getSeTuDescSlice(ctx, tc.seTuConfig)            if tc.wantErr {                require.Error(t, err)            } else {                require.NoError(t, err)                require.Equal(t, tc.getArchiveInfoSliceRes, res)            }        })    }}测试用例解释:测试用例"success"模拟了getSeTuDescSlice调用成功的情况,设置查询条件R18=0,Tags="tag1", "tag2",PicSize="large",期望返回多条图片信息;测试用例"error"模拟了getSeTuDescSlice调用失败的情况,设置查询条件R18=1,Tags="tag3",PicSize="small", "medium",期望返回错误信息。

生成的代码太长,几点总结

  • gomock代码可以正常生成,但是外部repo定义最好清晰明了,可以直接把interface定义贴上去,会被认知到。

  • 粘贴到ide中,发现主要问题是包名导入问题,简单修改即可

生成的代码有一些报错:

Golang怎么使用ChatGPT生成单元测试

修改引入的类型名后即可:

Golang怎么使用ChatGPT生成单元测试

修改后运行成功:

Golang怎么使用ChatGPT生成单元测试

如果需要生成后人工修改量更低的话,需要更精确的上下文信息(包名、函数定义、描述等)

一些痛点

  • ChatGPT单次对话有长度限制,所以一次尽量只进行一个函数的单元测试生成。

  • 需要外部 repo mock的待测函数,需要的上下文很多,并且引入的无关字段需要剪枝避免污染输入

  • 一些复杂的私有包,看起来是比较不好支持的(尝试过在prompt中教会他,但是效果不好)

  • 一些复杂逻辑和边界情况,ai可能口是心非(写的用例和表述不一致,比如经典的20%*20%=400%,但是他知道这是错的)

  • 对于分层不是很清晰的项目,对函数/repo打桩可能很困难,这个时候要描述清楚就比较困难了,gomonkey可能比较适用

其他用法

  • 写好测试方法,让gpt帮助扩充用例集

  • code review,下面的代码就是gpt给出的代码建议

帮我优化下面的代码// picCompress Modify size to compress pictures.func picCompress(picData []byte) (newPicData []byte, err error) {   oldBuf := bytes.NewBuffer(picData)   pic, _, err := image.Decode(oldBuf)   if err != nil {      return   }   newPic := resize.Resize(uint(pic.Bounds().Dx()/2), 0, pic, resize.Lanczos3)   var newBuf bytes.Buffer   err = png.Encode(&newBuf, newPic)   if err != nil {      return   }   newPicData, err = ioutil.ReadAll(&newBuf)   if err != nil {      return   }   return}
您好!下面是一个优化版的代码,主要改进在于:减少对象的创建,避免额外的内存分配和垃圾回收。增加错误检查,避免可能的错误被忽略。以下是优化版代码:// picCompress Modify size to compress pictures.func picCompress(picData []byte) ([]byte, error) {    reader := bytes.NewReader(picData)    pic, _, err := image.Decode(reader)    if err != nil {        return nil, err    }    newPic := resize.Resize(uint(pic.Bounds().Dx()/2), 0, pic, resize.Lanczos3)    var writer bytes.Buffer    err = png.Encode(&writer, newPic)    if err != nil {        return nil, err    }    return writer.Bytes(), nil}尝试减少了对象的创建,使用了 bytes.Reader 代替了 bytes.NewBuffer 和 ioutil.ReadAll。在处理图片过程中,使用 bytes.Buffer 代替了 newBuf 这个额外的对象。同时也将函数的返回值简化,只返回处理后的 []byte 和可能的错误,避免了空值的返回。最后,增加错误检查,保证代码健壮性。

到此,关于“Golang怎么使用ChatGPT生成单元测试”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

您可能感兴趣的文档:

--结束END--

本文标题: Golang怎么使用ChatGPT生成单元测试

本文链接: https://lsjlt.com/news/352082.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Golang怎么使用ChatGPT生成单元测试
    这篇文章主要介绍“Golang怎么使用ChatGPT生成单元测试”,在日常操作中,相信很多人在Golang怎么使用ChatGPT生成单元测试问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang怎么使用C...
    99+
    2023-07-05
  • Golang使用ChatGPT生成单元测试实践
    目录前言Part1 easy:单个函数,无复杂依赖Part2 normal :里面有一些外部importPart3 hard:对外部repo进行mock(gomock举例)一些痛点其...
    99+
    2023-03-19
    Golang ChatGPT单元测试 Golang ChatGPT
  • golang单元测试怎么应用
    Go语言中的单元测试是通过创建和运行Go源代码文件中的特殊函数来实现的。以下是如何使用Go的单元测试的步骤:1. 在源代码文件的同一...
    99+
    2023-10-21
    golang
  • Java怎么自动生成mock单元测试
    在Java中,我们可以使用Mockito等库来自动生成mock单元测试。 以下是一个示例: 首先,我们需要在项目的构建文件中添加M...
    99+
    2023-10-22
    java
  • idea单元测试自动生成怎么实现
    实现自动生成单元测试的方法可以分为以下几个步骤: 静态代码分析:通过静态代码分析工具(如静态代码分析器、AST解析器等),对待测...
    99+
    2023-10-22
    idea
  • java自动生成单元测试代码怎么写
    在Java中,可以使用各种框架来自动生成单元测试代码,比如JUnit、TestNG等。下面是使用JUnit框架来自动生成单元测试代码...
    99+
    2023-10-22
    java
  • 单元测试与集成测试在golang函数测试中的区别?
    单元测试和集成测试是两种不同的 go 函数测试类型,分别用于验证单个函数或多个函数的交互和集成。单元测试只测试特定函数的基本功能,集成测试测试多个函数之间的交互和与应用程序其他部分的集成...
    99+
    2024-04-27
    单元测试 集成测试 golang
  • Android自动化测试生成单元测试结果报告
      使用robotium进行Android应用进行自动化测试,之前用TMTS框架,但收集到的单元测试结果常常会少掉一些用例集。。穷则思变,Android的测试框架主要是通过...
    99+
    2022-06-06
    单元 测试结果 单元测试 测试 Android
  • GOLang单元测试用法详解
    目录概念go test基本用法go test 基础用例测试可执行程序外部测试包解决循环依赖测试覆盖比例测试基准函数概念 单元测试 UT测试,针对程序来进行正确检测测试工作,一个优秀强...
    99+
    2022-12-15
    GOLang单元测试 GO单元测试
  • 怎么使用React Testing Library和Jest完成单元测试
    这篇文章主要讲解了“怎么使用React Testing Library和Jest完成单元测试”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用React...
    99+
    2024-04-02
  • Java中怎么实现单元测试与集成测试
    Java中怎么实现单元测试与集成测试,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Maven测试代码结构的组织我们知道在Maven工程结构中“src/test”目录是专门用...
    99+
    2023-06-16
  • Golang函数生命周期中的单元测试
    单元测试对于确保 golang 函数的预期行为至关重要。本文介绍了在函数生命周期不同阶段进行单元测试的策略:测试初始化和终止:使用 runtime.beforealloc 和 runti...
    99+
    2024-04-18
    go 单元测试 golang
  • @SpringBootTest单元测试测试类的使用
    前言 使用SpringBoot 测试类可在不需要启动程序时,即可使用。当你运行你的测试方法时他会自己启动程序调用所需使用到的mapper,service接口,实现方法。故而可在测试类中像编写正常service方法一样编写代码 一.依赖录入 ...
    99+
    2023-08-21
    单元测试 junit java
  • 如何使用单元测试框架对 Golang 函数进行测试?
    go 中使用单元测试框架进行单元测试:导入 testing 包。编写以 test 为前缀的单元测试函数。使用断言函数(如 assertequal())验证测试结果。运行单元测试(go t...
    99+
    2024-04-16
    golang 单元测试 标准库
  • Java单元测试Mockito怎么用
    这篇文章将为大家详细讲解有关Java单元测试Mockito怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Mockito简介    调用mock对象的方法时,不会执行真实...
    99+
    2023-06-20
  • 怎么在SpringBoot中使用Mockito单元测试
    这期内容当中小编将会给大家带来有关怎么在SpringBoot中使用Mockito单元测试,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Mock 测试Mock 测试就是在测试过程中,创建一个假的对象,避免你...
    99+
    2023-06-15
  • C#怎么使用MSTest进行单元测试
    今天小编给大家分享一下C#怎么使用MSTest进行单元测试的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。目前MS发布了两个版...
    99+
    2023-07-02
  • Pytest单元测试框架生成HTML测试报告及优化的步骤
    目录一、安装插件IDE中安装命令行安装二、生成html报告三、使用小技巧指定路径报告独立四、报告优化一、安装插件   要生成html类型的报告,需要使用pytest-html插件,可...
    99+
    2024-04-02
  • 关于SpringBoot单元测试(cobertura生成覆盖率报告)
    目录demo(SpringBoot 项目)覆盖率测试报告生成(cobertura)cobertura 原理1.instrument2.执行测试3.生成报告SpringBoot pom...
    99+
    2024-04-02
  • 使用VisualStudio编写单元测试
    一、什么是单元测试 单元测试就是编写一段代码,用来检查某个特定条件下,另外一段代码的行为是否符合我们的预期。单元测试的代码与实际程序的代码具有同等的重要性。每一个单元测试,都是用来定...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作