ChatGPT生成單元測(cè)試實(shí)踐(Golang)

前言
目前gpt本質(zhì)上是續(xù)寫,所以在待測(cè)函數(shù)函數(shù)定義清晰的情況下,單元測(cè)試可以適當(dāng)依賴它進(jìn)行生成。
收益是什么:
輔助生成測(cè)試用例&測(cè)試代碼,降低單元測(cè)試編寫的心智成本
輔助code review,幫助發(fā)現(xiàn)代碼顯式/潛在問(wèn)題
本文測(cè)試環(huán)境:
gpt: gpt-3.5-turbo
go:go 1.17
本文實(shí)踐場(chǎng)景:企業(yè)微信美圖鑒賞機(jī)器人

生成單元測(cè)試的工作流如下:
選定你的待測(cè)函數(shù)
分析函數(shù)的依賴:結(jié)構(gòu)體定義、repo依賴、repo interface抽象(用bb框架的話會(huì)方便很多)
組織prompt,準(zhǔn)備施法
吟唱魔法,得到輸出單元測(cè)試代碼
copy到ide里面縫縫補(bǔ)補(bǔ),與預(yù)期出入太多的話,調(diào)整prompt重來(lái)/要求gpt按照某個(gè)標(biāo)準(zhǔn)重寫(比如:請(qǐng)按照testCases的寫法重寫組織測(cè)試數(shù)據(jù))
運(yùn)行測(cè)試用例
話不多說(shuō),先上基礎(chǔ)prompt:
下面的部分,我按照工作流的繁雜程度,簡(jiǎn)單區(qū)分了下easy/normal/hard情況。

Part1 easy:?jiǎn)蝹€(gè)函數(shù),無(wú)復(fù)雜依賴
單個(gè)函數(shù),并且外部依賴都是開源庫(kù),那么直接把代碼貼上去就行。
這里我們用圖片壓縮的獨(dú)立函數(shù)舉例: (prompt前搖咒語(yǔ) + 代碼片段)
ChatGPT輸出的代碼塊如下:
放到ide里,完美運(yùn)行,說(shuō)明簡(jiǎn)單函數(shù)的單元測(cè)試生成還是很強(qiáng)的~


Part2 normal :里面有一些外部import
有外部定義引入的時(shí)候,最好把外部定義直接貼上(不涉及mock)。
這里舉例的函數(shù)出現(xiàn)了外部依賴 entity.ArchiveWithData等定義,所以最好要加上外部定義在輸入中:
下面是生成的代碼,經(jīng)過(guò)少量修改后可以直接運(yùn)行:
(因?yàn)樯佥斎肓艘粋€(gè)結(jié)構(gòu)體的定義,導(dǎo)致它猜測(cè)了一些字段)


Part3 hard:對(duì)外部repo進(jìn)行mock(gomock舉例)
外部依賴越多,prompt template的構(gòu)建可能就越復(fù)雜
ps.實(shí)際上gomonkey它也可以寫
外部依賴repo的部分,要求gpt使用gomock進(jìn)行對(duì)應(yīng)repo的mock即可。
外部定義最好進(jìn)行剪枝。
輸出:
生成的代碼太長(zhǎng),幾點(diǎn)總結(jié):
1.gomock代碼可以正常生成,但是外部repo定義最好清晰明了,可以直接把interface定義貼上去,會(huì)被認(rèn)知到。
2.粘貼到ide中,發(fā)現(xiàn)主要問(wèn)題是包名導(dǎo)入問(wèn)題,簡(jiǎn)單修改即可


修改后運(yùn)行成功:

如果需要生成后人工修改量更低的話,需要更精確的上下文信息(包名、函數(shù)定義、描述等)

一些痛點(diǎn)
1.需要外部 repo mock的待測(cè)函數(shù),需要的上下文很多,并且引入的無(wú)關(guān)字段需要剪枝避免污染輸入
2.一些復(fù)雜的私有包,看起來(lái)是比較不好支持的(嘗試過(guò)在prompt中教會(huì)他,但是效果不好)
3.一些復(fù)雜邏輯和邊界情況,ai可能口是心非(寫的用例和表述不一致,比如經(jīng)典的20%*20%=400%,但是他知道這是錯(cuò)的)
4.對(duì)于分層不是很清晰的項(xiàng)目,對(duì)函數(shù)/repo打樁可能很困難,這個(gè)時(shí)候要描述清楚就比較困難了,gomonkey可能比較適用

其他用法
1.寫好測(cè)試方法,讓gpt幫助擴(kuò)充用例集
2.code review,下面的代碼就是gpt給出的代碼建議
ChatGPT給出的優(yōu)化建議: