1.png

在軟件開發(fā)的生命周期中,自動生成單元測試成為提高代碼質(zhì)量和開發(fā)效率的關(guān)鍵技術(shù)。在不久前舉辦的 QCon 全球軟件開發(fā)大會(上海站)上,字節(jié)跳動質(zhì)量效能專家趙亮作了《基于 LLM 的單元測試用例自動生成》的精彩演講。針對字節(jié)研發(fā)內(nèi)部需求,基于大模型技術(shù)結(jié)合深度程序分析,實(shí)現(xiàn)存量及增量單元測試的自動生成。本文為 InfoQ 整理的演講實(shí)錄。

我將與大家分享我們團(tuán)隊(duì)在大模型自動生成單元測試方面的研發(fā)經(jīng)歷,這個(gè)議題涵蓋了我們從問題識別到解決方案的全過程。我將這個(gè)議題分為六個(gè)部分。

  1. 痛點(diǎn)與現(xiàn)狀。這部分涉及到我們?yōu)楹我纸鉀Q這個(gè)問題,以及我們與業(yè)務(wù)團(tuán)隊(duì)合作時(shí)收集到的問題和痛點(diǎn)。這些痛點(diǎn)和現(xiàn)狀是我們行動的出發(fā)點(diǎn)。

  2. 目標(biāo)與挑戰(zhàn)?;谇捌谑占膯栴},我們設(shè)定了一系列目標(biāo),并在實(shí)現(xiàn)這些目標(biāo)的過程中遇到了一系列的挑戰(zhàn)。

  3. 數(shù)據(jù)質(zhì)量提升。分享我們?yōu)榱颂嵘龁螠y生成效果所做的工作,以及我們?nèi)绾瓮ㄟ^這些措施來提高整體效果。

  4. 代碼生成效果提升。介紹我們采用的一些方法,以提升模型在生成單元測試方面的性能。

  5. 效果演示。展示我們所取得的一些成果,讓大家更直觀地了解我們的工作效果。

  6. 總結(jié)與規(guī)劃。總結(jié)我們在整個(gè)過程中的不足之處,并分享我們的一些思考和未來的規(guī)劃。

現(xiàn)狀痛點(diǎn)

許多有編寫單元測試經(jīng)驗(yàn)的人普遍面臨一個(gè)問題: 業(yè)務(wù)代碼的單元測試覆蓋率普遍不高。 這并非因?yàn)殚_發(fā)人員不愿意編寫測試,而是因?yàn)樗麄儧]有足夠的時(shí)間。 許多業(yè)務(wù)的上線時(shí)間緊迫,留給開發(fā)代碼的時(shí)間本就不多,更不用說編寫單元測試了。 在這種情況下,開發(fā)人員往往將質(zhì)量保障工作交給測試團(tuán)隊(duì),但測試團(tuán)隊(duì)的主要精力在于驗(yàn)證需求和功能的正確性,而不是逐行審查代碼。

我將這些問題歸納為三個(gè)主要部分:

首先,編寫單元測試耗時(shí)較長。 在與業(yè)務(wù)團(tuán)隊(duì)的研發(fā)人員溝通時(shí),我們發(fā)現(xiàn)編寫單元測試的時(shí)間可能比編寫業(yè)務(wù)代碼還要長,這取決于被測方法的數(shù)據(jù)復(fù)雜度和代碼復(fù)雜度。平均而言,編寫單元測試的時(shí)間大約需要 5 到 15 分鐘,取決于目標(biāo)被測函數(shù)的邏輯復(fù)雜度和數(shù)據(jù)構(gòu)造的困難程度。

其次,由于業(yè)務(wù)上線時(shí)間緊迫,研發(fā)人員可能同時(shí)處理多個(gè)需求,導(dǎo)致他們沒有精力保證單元測試的編寫,這使得存量問題愈發(fā)嚴(yán)重。 例如,我們內(nèi)部許多業(yè)務(wù)團(tuán)隊(duì)由于快速迭代導(dǎo)致大量未編寫單元測試的代碼,許多倉庫的代碼行覆蓋率小于 10%,這使得暴露給線上的風(fēng)險(xiǎn)非常大。

最后,現(xiàn)有工具的效果不足。 盡管許多公司和團(tuán)隊(duì)嘗試通過工程化方法或基于搜索、遺傳算法的單元測試生成方式,以及近年來隨著大模型的興起,嘗試使用模型生成單元測試,但普遍存在幾個(gè)問題:生成數(shù)據(jù)的可讀性低,用例多樣性不穩(wěn)定,以及編譯通過率低。這些問題導(dǎo)致生成的單元測試存在許多編譯或運(yùn)行問題,增加了研發(fā)人員修正的成本。

目標(biāo)及挑戰(zhàn)

目標(biāo)

對單元測試的現(xiàn)狀和痛點(diǎn),我們設(shè)定了明確的目標(biāo),并將其拆解為幾個(gè)關(guān)鍵部分,以期通過這些目標(biāo)來解決我們面臨的問題。

首先,盡管模型和插件如 Copilot 在代碼生成方面取得了一定的進(jìn)展,但它們還不能完全理解業(yè)務(wù)需求,也不能保證 100% 的編譯通過率。因此,我們基于工程分析建立了精準(zhǔn)的數(shù)據(jù)分析基礎(chǔ),以此為我們的單元測試生成產(chǎn)品提供支撐。我們的目標(biāo)是提高工程化分析的準(zhǔn)確性,通過將控制分析、數(shù)據(jù)分析和約束求解的方案相結(jié)合提升前期單測數(shù)據(jù)語料分析的精確性。

其次,我們對模型本身也設(shè)定了目標(biāo)。我們正在嘗試并將持續(xù)引入偏好對齊和強(qiáng)化學(xué)習(xí)算法,以及已經(jīng)在使用的思維鏈方式和微調(diào)技術(shù),以持續(xù)提高模型在生成單元測試方面的效果。

最后,我們希望提升單元測試生成產(chǎn)品的用戶體驗(yàn)。我們的目標(biāo)是打造一個(gè)開箱即用、快速且輕量化的單元測試工具,以降低業(yè)務(wù)研發(fā)人員的使用成本。

在目標(biāo)設(shè)定上明確了四個(gè)具體的目標(biāo): 覆蓋率目標(biāo)、有效性目標(biāo)(包括斷言、mock 和流量)、目標(biāo)倉庫覆蓋目標(biāo),以及研發(fā)投入產(chǎn)出比目標(biāo)。

在代碼質(zhì)量與研發(fā)效能之間,我們面臨著一個(gè)場景權(quán)衡。我們希望在保證代碼質(zhì)量的同時(shí),又不會犧牲較多的需求迭代時(shí)長。業(yè)務(wù)的快速上線對于市場份額的占領(lǐng)至關(guān)重要,因此我們希望通過這套工具打破原有的平衡,既保障代碼質(zhì)量,又提升業(yè)務(wù)研發(fā)的效率。

挑戰(zhàn)

在研發(fā)過程中,我們遇到了不少挑戰(zhàn),其中兩個(gè)尤為關(guān)鍵: 數(shù)據(jù)質(zhì)量和代碼生成效果。

首先,數(shù)據(jù)質(zhì)量是我們面臨的一個(gè)重大挑戰(zhàn),它可以分為三個(gè)部分。第一部分是模型訓(xùn)練,眾所周知,訓(xùn)練數(shù)據(jù)集的質(zhì)量直接影響模型的最終效果,這比選擇哪種模型基座或訓(xùn)練方式更為重要。第二部分是提示詞的目標(biāo)性,即使模型訓(xùn)練效果再好,如果提示詞不明確,模型生成的內(nèi)容也可能出現(xiàn)幻覺或達(dá)不到預(yù)期的問題。第三部分是業(yè)務(wù)研發(fā)側(cè)關(guān)注的數(shù)據(jù)準(zhǔn)確性、有效性和真實(shí)性。生成的單元測試所構(gòu)造的數(shù)據(jù)必須與業(yè)務(wù)高度匹配或近似,因?yàn)槟P陀袝r(shí)會生成一些不符合業(yè)務(wù)邏輯的數(shù)據(jù),比如電話號碼,模型可能將其理解為基礎(chǔ)變量而生成不真實(shí)的數(shù)字,這對于業(yè)務(wù)來說是不可接受的。

其次,代碼生成效果也是我們關(guān)注的重點(diǎn)。我們希望通過工程化的方式,結(jié)合現(xiàn)有模型的能力,使代碼生成在風(fēng)格和業(yè)務(wù)語義上具有更好的包容性。這對于業(yè)務(wù)是否采納單元測試至關(guān)重要。我們期望生成的代碼不僅在技術(shù)上無誤,而且在風(fēng)格和語義上與業(yè)務(wù)需求相匹配,以便業(yè)務(wù)研發(fā)團(tuán)隊(duì)能夠輕松地采納和集成這些單元測試。

數(shù)據(jù)質(zhì)量提升:工程化分析解決數(shù)據(jù)難題

數(shù)據(jù)充分度提升

在提升數(shù)據(jù)質(zhì)量方面,我們采取了一系列工程化的分析方法來協(xié)助模型解決數(shù)據(jù)難題。我們主要關(guān)注兩個(gè)問題:數(shù)據(jù)的真實(shí)性和充分度如何提升,以及如何確保模型的提示詞數(shù)據(jù)能夠被準(zhǔn)確理解。以下是我們面臨的幾個(gè)具體問題和相應(yīng)的解決方案。

首先,被測方法的入?yún)?gòu)造非常復(fù)雜,不僅僅是基礎(chǔ)變量,還包括復(fù)雜的結(jié)構(gòu)體或嵌套結(jié)構(gòu)體,這使得在編寫單元測試時(shí)構(gòu)造數(shù)據(jù)的難度大大增加。其次,脫離業(yè)務(wù)理解生成的數(shù)據(jù)價(jià)值不高,這是我們與業(yè)務(wù)團(tuán)隊(duì)溝通后得出的結(jié)論。第三,出入?yún)⒌南嚓P(guān)性不足,有些函數(shù)依賴大量數(shù)據(jù)庫、外部 RPC 或三方組件,這些依賴數(shù)據(jù)的變化會導(dǎo)致目標(biāo)函數(shù)的條件路徑發(fā)生變化,這是一個(gè)關(guān)鍵環(huán)節(jié)。最后,斷言的目標(biāo)性是否準(zhǔn)確將決定生成的單元測試是否具備一定的有效性和通過率。

針對這些問題,我們提出了一個(gè)三部分的解決方案。 第一部分是基于流量來源的收集和采納。 首先,我們與業(yè)務(wù)團(tuán)隊(duì)溝通后發(fā)現(xiàn),真實(shí)的流量主要來自真實(shí)的手工測試或線上業(yè)務(wù)流量,這是一部分來源。其次是接口自動化,其維護(hù)成本和時(shí)間成本相比編寫單元測試要低一些,通過業(yè)務(wù)真實(shí)定義的接口自動化能夠?qū)崿F(xiàn)函數(shù)鏈路間的調(diào)用,從而實(shí)現(xiàn)函數(shù)級數(shù)據(jù)的采集。最后是測試技術(shù)服務(wù),包括模糊測試和端到端全流量回放技術(shù),結(jié)合代碼插樁技術(shù),攔截代碼中的出入?yún)⒑鸵蕾噮?shù)。從而獲取數(shù)據(jù)流量中具體參數(shù)值信息作為單測生成的數(shù)據(jù)來源。

第二部分是流量蒸餾。 這些數(shù)據(jù)不僅用于單元測試生成對應(yīng)的出入?yún)?gòu)造,還有一部分?jǐn)?shù)據(jù)將作為模型訓(xùn)練和提示詞工程的數(shù)據(jù)語料。因此,我們需要對數(shù)據(jù)進(jìn)行基本類型策略的管理和拆解,包括數(shù)據(jù)的分析、路徑推導(dǎo)、導(dǎo)入導(dǎo)出類型的拆解,以及后期的數(shù)據(jù)加工和合規(guī)隱私處理。由于我們獲取的線上流量中包含真實(shí)用戶數(shù)據(jù),我們需要對這些數(shù)據(jù)進(jìn)行脫敏,確保數(shù)據(jù)的真實(shí)性不被泄露。

第三部分是流量分發(fā)。 經(jīng)過流量蒸餾后的數(shù)據(jù)將分發(fā)給幾個(gè)場景,包括存量生成、面向 IDE 的數(shù)據(jù)生成,以及面向 MR 流水線的單元測試生成過程。

通過實(shí)施我們的數(shù)據(jù)充分度提升方案,我們?nèi)〉昧艘恍╋@著的數(shù)據(jù)結(jié)果。例如,在沒有使用流量構(gòu)造方法之前,生成的單元測試中包含了一個(gè) mock 構(gòu)造函數(shù),這個(gè)函數(shù)雖然具備了基本的框架,但是其內(nèi)部的數(shù)據(jù)結(jié)構(gòu)字段缺失嚴(yán)重,模型并沒有完全理解它。當(dāng)我們引入流量構(gòu)造方案后,情況有了顯著的改善。新的數(shù)據(jù)結(jié)構(gòu)中包含了大量豐富的數(shù)據(jù)語料,這些數(shù)據(jù)更加貼近真實(shí)業(yè)務(wù)場景,因此業(yè)務(wù)團(tuán)隊(duì)對這些單元測試的接受度和采納率大大提高。與以往僅依賴模型或工程方法相比,我們在數(shù)據(jù)利用率和用例真實(shí)性占比上都有了明顯的提升。首先,我們看到了用例的可信度得到了顯著提升。其次,用戶的采納率也有所增加。最后,問題的發(fā)現(xiàn)率也有所提高。

等價(jià)類提升思想

在進(jìn)行單元測試時(shí),我們不僅關(guān)注于發(fā)現(xiàn)問題,還致力于提升測試覆蓋率。為此,我們采用了等價(jià)類設(shè)計(jì)等方法,并在前期對現(xiàn)狀問題進(jìn)行了梳理。以下是我們關(guān)注的幾個(gè)關(guān)鍵部分:

  1. 被測方法中存在許多復(fù)雜路徑,我們需要識別這些路徑,并確保模型在生成過程中能夠覆蓋到這些路徑。這是一個(gè)挑戰(zhàn),因?yàn)槁窂降膹?fù)雜性可能會導(dǎo)致測試用例無法覆蓋到所有可能的情況。

  2. 模型推理過程中非常依賴于提示詞的準(zhǔn)確性和完整度。如果提示詞不準(zhǔn)確或不完整,模型生成的測試用例可能無法達(dá)到預(yù)期的效果。

  3. 路徑條件的差異可能導(dǎo)致斷言失敗。例如,如果預(yù)期是通過路徑 1 或 2 到達(dá)斷言點(diǎn),但實(shí)際生成的測試用例卻通過路徑 2 或 4 到達(dá),那么斷言可能會失敗,導(dǎo)致業(yè)務(wù)團(tuán)隊(duì)需要修復(fù)大量的失敗案例。

  4. 異常路徑的考慮。在時(shí)間緊張的情況下,開發(fā)人員可能只會編寫主要路徑的單元測試,而忽視了異常路徑,如異常捕獲或難以到達(dá)的小模塊路徑。這些路徑的參數(shù)構(gòu)造復(fù)雜度高,且難以覆蓋。

  5. 對于已有的單元測試,我們的目標(biāo)是提升那些測試覆蓋率較低的存量代碼。我們需要確保新生成的單元測試與業(yè)務(wù)代碼風(fēng)格保持一致,并且避免重復(fù)已有測試用例已經(jīng)覆蓋的類目。

我們目前的解決方案是將模型和工程方法相結(jié)合,以解決單元測試中的路徑覆蓋問題。以一個(gè)具體的函數(shù)為例,該函數(shù)包含多個(gè)調(diào)用分支路徑。我們的目標(biāo)是讓測試能夠覆蓋到特定的路徑,比如 ACD 或 ACE 路徑。在拿到原始的被測方法后,我們會通過工程化的方式將其調(diào)用路徑拆解出來。拆解后,模型會對 mock 層和依賴返回?cái)?shù)據(jù)做出決策并生成測試用例。生成測試用例后,我們會在閉環(huán)迭代中持續(xù)優(yōu)化矯正,直到測試路徑達(dá)到預(yù)期條件。在這個(gè)過程中,我們會結(jié)合靜態(tài)代碼分析的能力,識別未覆蓋的路徑和條件是否真正達(dá)到了我們的生成預(yù)期。如果達(dá)到了,那么這個(gè)測試用例就可以被認(rèn)為是符合預(yù)期的。

在整個(gè)拆解過程中,我們分為三個(gè)部分: 被測函數(shù)的要素分析、邏輯分析和路徑分析。 我們會利用 AST 和 IR 等程序分析技術(shù),對代碼中的控制流和數(shù)據(jù)流進(jìn)行條件組合關(guān)系的前期拆解。具體來說,我們首先將被測方法中的入?yún)ⅰ⒊鰠⒑椭虚g變量參數(shù)拆解為可控變量。通過對這些可控變量的分析,我們能夠完成數(shù)據(jù)流的前期分析工作,為后續(xù)的測試用例生成打下基礎(chǔ)。然后,在邏輯分析階段,我們關(guān)注于代碼中的分支類型控制組合以及變量溯源過程。這一步驟涉及到理解代碼中的邏輯結(jié)構(gòu),包括條件語句、循環(huán)語句等,以及變量是如何在這些邏輯結(jié)構(gòu)中被操作和傳遞的。最終,我們將這些分析結(jié)果綜合起來,進(jìn)行路徑分析。路徑分析的目的是識別代碼中所有可能的執(zhí)行路徑,包括路徑 X、路徑 Y 和路徑 Z 等。這些路徑的前期拆解條件對于模型來說至關(guān)重要,因?yàn)樗鼈優(yōu)槟P吞峁┝嗽谏刹煌窂降膯卧獪y試時(shí)所需的詳細(xì)信息和依據(jù)。

數(shù)據(jù)的效果和模塊的價(jià)值在這個(gè)過程中非常重要,它們不僅為模型推理提供了語料補(bǔ)充,還為斷言生成提供了支持依據(jù)。此外,這些數(shù)據(jù)對于我們后續(xù)計(jì)劃中的存量單元測試的保鮮也是一個(gè)重要的環(huán)節(jié)。

模型與程序分析的融合

在我們的工作中,模型與程序分析的融合是一個(gè)關(guān)鍵的發(fā)展方向。在這一過程中,工程化的方法和模型各自承擔(dān)著不同的角色。這個(gè)過程可以分為三個(gè)階段:首先,在程序分析的前期,我們需要對目標(biāo)函數(shù)的語料進(jìn)行拆解和解析。這一步驟是基礎(chǔ),為后續(xù)的模型生成框架補(bǔ)充和路徑提升提供必要的數(shù)據(jù)。接著,模型會利用這些解析后的數(shù)據(jù)進(jìn)行生成框架的補(bǔ)充和路徑的提升。在單元測試生成過程中,由于不能保證所有生成的測試都能一次性通過,因此還需要進(jìn)行語法修正。最后,對于斷言部分,我們也有相應(yīng)的修正策略。

2.png

總結(jié)這一融合過程,我們可以從兩個(gè)方面來看其優(yōu)勢。首先,工程化方法的優(yōu)勢在于其對代碼分析的準(zhǔn)確率和穩(wěn)定性。程序分析技術(shù)在國內(nèi)已經(jīng)應(yīng)用多年,因此在分析的準(zhǔn)確性和穩(wěn)定性上具有很高的水平。由于單元測試需要實(shí)際運(yùn)行來驗(yàn)證效果,工程化方法具備檢測運(yùn)行的能力。其次,模型的優(yōu)勢在于其靈活性和泛化效果。模型在靈活決策和泛化效果上比工程化的固定策略要好,這也是現(xiàn)在很多智能代理所做的事情。

這里我總結(jié)了兩個(gè)關(guān)鍵點(diǎn)以及模型生成和模型修復(fù)所需的語料條件:

首先,當(dāng)模型生成時(shí),它需要一些特定的條件數(shù)據(jù),包括路徑數(shù)據(jù)、函數(shù)簽名以及依賴結(jié)構(gòu)體的定義。這些數(shù)據(jù)對于模型來說是至關(guān)重要的,因?yàn)樗鼈儤?gòu)成了模型生成所需語料的基礎(chǔ)。

其次,在模型修復(fù)方面,我們需要修復(fù)在編譯或運(yùn)行過程中遇到的問題。例如,如果在運(yùn)行過程中出現(xiàn)了錯(cuò)誤堆棧,我們需要將這些具體的報(bào)錯(cuò)信息提供給模型,以便它能夠更好地理解并進(jìn)行修復(fù)。這包括錯(cuò)誤相關(guān)的數(shù)據(jù)結(jié)構(gòu)和錯(cuò)誤類型。簡而言之,當(dāng)我們希望模型進(jìn)行修復(fù)時(shí),提供給它的信息和語料越詳細(xì),模型的準(zhǔn)確性就越高,同時(shí)它需要考慮的約束范圍也就越小。

代碼生成效果提升:模型化建設(shè)提升代碼效果

這一部分重點(diǎn)介紹我們在單元測試生成過程中,通過模型實(shí)現(xiàn)的一些關(guān)鍵進(jìn)展,可以分 為四個(gè)主要部分:

  1. 模型泛化效果如何提升。這是至關(guān)重要的,因?yàn)樗鼪Q定了模型在面對未知代碼時(shí)是否能夠生成有效的測試用例。

  2. 模型提示詞選擇策劃。在生成過程中,選擇合適的提示詞對于引導(dǎo)模型生成高質(zhì)量的測試代碼非常關(guān)鍵。

  3. 無流量單側(cè)方法如何生成有效的單測數(shù)據(jù)。盡管我們嘗試使用真實(shí)的業(yè)務(wù)流量來生成單元測試,但在這個(gè)過程中,我們遇到了一些挑戰(zhàn)。例如,一些業(yè)務(wù)的流量非常有限,或者某些方法根本沒有被執(zhí)行到。此外,由于工程的不穩(wěn)定性,我們收集到的數(shù)據(jù)往往是不完整的。因此,我們研究了如何利用模型來補(bǔ)全這些無流量的數(shù)據(jù),以便對未被測試的方法進(jìn)行測試。

  4. 模型效果生成評價(jià)。對模型的評測是能夠持續(xù)不斷的矯正和確認(rèn)效果是否提升的主要方式,將輔助我們持續(xù)調(diào)整正確的方向。

模型工程整體架構(gòu)

模型工程的整體架構(gòu)。最底層是數(shù)據(jù)環(huán)節(jié),包括數(shù)據(jù)的收集和訓(xùn)練評估工作,其中有些工作仍在進(jìn)行中。

我們的數(shù)據(jù)訓(xùn)練策略分為三個(gè)步驟:

STEP1 訓(xùn)練樣本構(gòu)建。我們選擇了內(nèi)部大量的代碼庫作為數(shù)據(jù)來源,這是因?yàn)椴煌驹诰帉憜卧獪y試時(shí)會使用自己的測試框架和標(biāo)準(zhǔn),這有助于模型更好地理解公司內(nèi)部的標(biāo)準(zhǔn)和組件使用策略。其次,我們選擇了 GitHub 上星標(biāo)高的項(xiàng)目作為訓(xùn)練目標(biāo),以確保數(shù)據(jù)的質(zhì)量和多樣性。第三,對于數(shù)據(jù)量有限的小場景或特殊組件使用情況,我們會借助市面上效果較好的模型,如 GPT,來擴(kuò)充我們的模型。第四,我們正在進(jìn)行基于反饋的優(yōu)化,但這部分的優(yōu)化工作尚未完全啟動。

STEP2 模型的選用。經(jīng)過前期的嘗試,我們最終選取了一款適用于本項(xiàng)目的模型作為后期持續(xù)訓(xùn)練基座。在提示詞的選取上,我們從單純的 one-shot 或 few-shot 方案轉(zhuǎn)變?yōu)榻Y(jié)合思維鏈的方案,這在路徑提升、語法修正和斷言生成方面取得了顯著的效果。

STEP3 模型的評測及優(yōu)化。我們采用人工主觀評測和機(jī)器評測相結(jié)合的方式,通過評測結(jié)果進(jìn)行偏好打分,并將優(yōu)質(zhì)數(shù)據(jù)反饋給模型進(jìn)行多輪迭代,以持續(xù)提升模型效果。

3.png

數(shù)據(jù)工程建設(shè)

在數(shù)據(jù)工程建設(shè)方面,我們需要確保數(shù)據(jù)集的可信度和純凈度。我們希望數(shù)據(jù)集中包含多種編程語言,以覆蓋不同的編程階段。同時(shí),我們將其細(xì)分為六個(gè)關(guān)鍵環(huán)節(jié),以確保數(shù)據(jù)的質(zhì)量和有效性,從而提升大模型的理解能力和泛化效果。

  1. 樣本打標(biāo),是至關(guān)重要的一步。通過為樣本打標(biāo),我們幫助大模型更好地理解數(shù)據(jù),同時(shí),打標(biāo)數(shù)據(jù)的多樣性也有助于進(jìn)行多樣化評估。這種評估能夠使模型在更廣泛的模式中學(xué)習(xí),進(jìn)而提高模型的泛化能力。

  2. 樣本篩選,采用業(yè)界標(biāo)準(zhǔn)做法,排除低質(zhì)量數(shù)據(jù)。

  3. 隱私過濾,處理隱私相關(guān)問題,確保數(shù)據(jù)的合規(guī)性和安全性。

  4. 格式處理,數(shù)據(jù)風(fēng)格的統(tǒng)一和特殊字符的處理。我們進(jìn)行一系列的數(shù)據(jù)優(yōu)化工作,以確保數(shù)據(jù)的一致性和可讀性。

  5. 數(shù)據(jù)簡化,是我們特別關(guān)注的一個(gè)環(huán)節(jié),尤其是在代碼簡化方面。這不僅有助于單元測試的生成,也提升了模型訓(xùn)練的效果。通過簡化數(shù)據(jù),我們能夠更有效地訓(xùn)練模型,使其能夠更快地學(xué)習(xí)和適應(yīng)。

  6. 數(shù)據(jù)配比打亂,確保數(shù)據(jù)來源多樣性的關(guān)鍵步驟。由于數(shù)據(jù)往往是分塊收集的,我們需要混合這些數(shù)據(jù),以實(shí)現(xiàn)多元學(xué)習(xí)的效果。這種混合數(shù)據(jù)能夠提供更全面的學(xué)習(xí)場景,進(jìn)一步增強(qiáng)模型的性能。

在代碼簡化方面,我們面臨的一個(gè)主要挑戰(zhàn)是業(yè)務(wù)代碼中的業(yè)務(wù)語義非常多。這些代碼在字段命名、方法體命名以及變量命名上都具有很強(qiáng)的業(yè)務(wù)特定性,這對于模型來說增加了額外的學(xué)習(xí)成本。為了解決這個(gè)問題,我們采用了一些來自業(yè)界和學(xué)術(shù)界的優(yōu)秀思路,制定了一個(gè)簡化方案。

我們的方案主要包括兩個(gè)部分。首先,我們嘗試從代碼中抽取關(guān)鍵數(shù)據(jù),保留函數(shù)聲明、函數(shù)調(diào)用語句、控制流和變量信息,以及 return 信息。這樣,我們可以剔除那些復(fù)雜的日志處理和不影響路徑的無關(guān)內(nèi)容,從而簡化代碼。其次,我們對那些業(yè)務(wù)語義重的字段進(jìn)行轉(zhuǎn)譯。例如,將“中國建設(shè)銀行”這樣的字段轉(zhuǎn)譯為 Y0、Y1、Y2 等,這樣做既保留了代碼的原貌,又不會影響代碼邏輯。通過這種方式,我們可以減輕模型訓(xùn)練的負(fù)擔(dān)。

此外,我們還注意到不同編程語言中,如 Python、Go、Java 或 C++,這些語言對應(yīng)的 print 函數(shù)的實(shí)現(xiàn)方式各不相同。因此,我們對這些不同編程語言的差異進(jìn)行了簡化,統(tǒng)一為模型可識別的 print 操作。在模型完成代碼生成后,我們再根據(jù)之前的轉(zhuǎn)譯規(guī)則將代碼轉(zhuǎn)換回原始形式,以獲得更準(zhǔn)確的結(jié)果。在代碼簡化之前,我們觀察到 loss 的下降和收斂效果非常慢。但在實(shí)施代碼簡化后,與之前未簡化的代碼訓(xùn)練過程相比,loss 的下降趨勢明顯改善。這表明代碼簡化對于模型訓(xùn)練的效率和效果都有積極的影響。

PE 工程及模型微調(diào)

PE 工程路徑規(guī)劃覆蓋了多個(gè)方面,包括對被測代碼的理解、路徑識別、入?yún)⒗斫?,以?mock 規(guī)劃,這些都是為了確定哪些 mock 會導(dǎo)致不同路徑的執(zhí)行。最終,我們讓模型學(xué)習(xí)并生成求解。在這個(gè)過程中,我們將工作細(xì)分為四個(gè)主要部分:路徑提升、參數(shù)補(bǔ)全、語法修正和斷言修正。實(shí)驗(yàn)結(jié)果表明,不同的提示詞方式對效果有顯著差異。例如,在參數(shù)補(bǔ)全方面,如果提供樣本,模型可能會模仿這些樣本來構(gòu)造輸出,這會影響其在真實(shí)業(yè)務(wù)語義上的泛化效果。相反,使用 zero-shot 的方式,即不給模型任何樣本,有時(shí)會得到比預(yù)期更好的結(jié)果。

我們目前主要處于模型微調(diào)階段,我們還希望通過結(jié)合微調(diào)和獎(jiǎng)勵(lì)模型來進(jìn)一步提升效果,未來可能會涉及到 PPO,但鑒于資源和成本的考慮,我們尚未開始這一階段。我們的目標(biāo)是生成一個(gè)策略模型實(shí)現(xiàn)持續(xù)的強(qiáng)化學(xué)習(xí)反饋和單測生成的動態(tài)決策。

評測工程建設(shè)及效果

我們針對評測集設(shè)計(jì)了不同階段的專項(xiàng)評測集,以便模型進(jìn)行更精確的評測。

在評測工程建設(shè)方面,目前已經(jīng)實(shí)施了一系列基礎(chǔ)評估工作,這包括了之前提到的人工評估,以及我們針對業(yè)務(wù)和產(chǎn)品制定的五個(gè)評測指標(biāo):編譯通過率、覆蓋率、斷言成功率、運(yùn)行通過率,以及路徑提升效果,我們通過這些指標(biāo)來進(jìn)行綜合評估。

目前,我們正處于基于 DPO 的多輪偏好學(xué)習(xí)提升階段,這是我們期望通過持續(xù)優(yōu)化來改善的效果。在訓(xùn)練效果方面,與原始模型相比,我們在斷言修復(fù)、語法修復(fù)和路徑提升方面取得了更好的成果。盡管在語法修正方面,我們的效果仍然略遜于 GPT 模型,但我們正在不斷優(yōu)化數(shù)據(jù)和訓(xùn)練方案,以期提升這一方面的表現(xiàn)。

效果度量及演示

我們對度量工作進(jìn)行了細(xì)致的拆分,主要關(guān)注兩個(gè)方面的提升:覆蓋率和場景支持。

目前,我們在倉庫級的覆蓋率上已經(jīng)取得了顯著的成績,平均覆蓋率達(dá)到了 40%。通過采用基于 DPO 的偏好方案進(jìn)行重訓(xùn)后,部分倉庫的覆蓋率甚至提升到了 60%。這是在我們已經(jīng)生成過的倉庫基礎(chǔ)上,通過重新生成得到的成果。在斷言通過率上,我們也達(dá)到了一個(gè)較高的水平,單個(gè)方法的覆蓋率提升到了 83.09%。

在場景支持方面,我們結(jié)合工程實(shí)踐來輔助模型,包括在指標(biāo)統(tǒng)計(jì)和數(shù)據(jù)優(yōu)化策略上,都提供了策略上的支持。我們的目標(biāo)是向業(yè)務(wù)研發(fā)交付一個(gè)無需二次介入修正的單測生成產(chǎn)品。這意味著提供的單元測試在編譯、運(yùn)行、語法和斷言上都不存在問題,業(yè)務(wù)研發(fā)只需審查生成的單元測試是否符合預(yù)期即可。

最關(guān)鍵的是,我們需要確保每個(gè)測試用例對真實(shí)路徑的提升都是有價(jià)值的。我們模擬了整個(gè)單元測試的生成流程。這包括流量獲取、路徑選擇、單元測試生成、語法修正、檢測、斷言修復(fù)以及路徑提升識別。如果一個(gè)測試用例已經(jīng)提升了路徑,我們就認(rèn)為這個(gè)案例是成功的,并繼續(xù)下一個(gè)路徑的提升。在斷言檢測過程中,我們發(fā)現(xiàn)有些斷言并不符合預(yù)期,例如,預(yù)期為 false 但實(shí)際上生成的結(jié)果是 true,這也是需要我們持續(xù)優(yōu)化和矯正的場景 case。

而對于業(yè)務(wù)的訴求而言,例如,我們向業(yè)務(wù)交付的倉庫之前沒有任何單元測試,這也是他們的一個(gè)痛點(diǎn)。通過我們的生成,目前效果達(dá)到了 63.92%,生成了 2,627 個(gè)測試用例。面對生成的 2,627 個(gè)單元測試用例,我們深知業(yè)務(wù)后續(xù)的維護(hù)工作將面臨挑戰(zhàn),因?yàn)榫S護(hù)這些測試的成本相對較高,而且逐個(gè)檢查每個(gè)測試用例的難度也較大,不如自己編寫的代碼容易理解。為了解決這一問題,我們已經(jīng)規(guī)劃并實(shí)施了一系列措施,將在可維護(hù)性和可讀性上為用戶持續(xù)提升便利。

總結(jié)及規(guī)劃

總結(jié)目前我們已經(jīng)完成的工作。 首先在 基礎(chǔ)層 上我們完成的工作包括能力分析、數(shù)據(jù)構(gòu)建,以及環(huán)境問題的解決。 這些基礎(chǔ)工作 為后續(xù)的測試維護(hù)提供了堅(jiān)實(shí)的支撐。 第二層 生成層 ,這涉及到整個(gè)單元測試框架的生成、路徑提升以及數(shù)據(jù)轉(zhuǎn)換過程。 通過這些優(yōu)化,我們提高了測試生成的效率和質(zhì)量。 第三層 修正層 ,這里我們實(shí)施了一些修正方案,包括語法修正、運(yùn)行修正以及斷言修正。 這些方案有助于確保生成的測試用例在語法和邏輯上的正確性,減少后續(xù)的維護(hù)工作。 最上層是統(tǒng)計(jì) & 應(yīng)用層,提供業(yè)務(wù)產(chǎn)品化體驗(yàn)?zāi)芰Γ?60°可視化度量體系,提升可觀測性。

在規(guī)劃方面,我們目前的工作重點(diǎn)包括模型的持續(xù)優(yōu)化、用例召回分析、用例保鮮機(jī)制以及產(chǎn)品多元化。這些是我們持續(xù)進(jìn)行的工作,其中用例召回分析和用例保鮮機(jī)制是我們目前特別關(guān)注的兩個(gè)方面。其中,

用例召回分析是指我們生成了許多測試用例后,如何檢測這些用例的召回有效性是否具有價(jià)值。這些用例會在業(yè)務(wù)的日常迭代的持續(xù)集成(CI)環(huán)節(jié)中運(yùn)行。如果運(yùn)行后出現(xiàn)失敗的用例,我們需要分析失敗的原因。目前,我們的初步思路是結(jié)合模型來識別關(guān)鍵日志和平臺性數(shù)據(jù)中的異常,進(jìn)行問題的深入分析。這個(gè)過程中,我們會進(jìn)行降噪,因?yàn)?CI 中的用例失敗可能不僅僅是問題的發(fā)現(xiàn),還可能因?yàn)榄h(huán)境因素或平臺因素導(dǎo)致,這些都需要我們進(jìn)行降噪處理。

用例保鮮則是指如何在日常業(yè)務(wù)研發(fā)中持續(xù)保證上述示例介紹的 2,000 多個(gè)用例的有效性和正常通過率。這是一個(gè)我們正在努力的目標(biāo),目的是確保這些用例能夠適應(yīng)業(yè)務(wù)的變化,保持其準(zhǔn)確性和相關(guān)性。

演講嘉賓介紹

趙亮,13 年工作經(jīng)驗(yàn),先后在螞蟻集團(tuán)余額寶質(zhì)量技術(shù)和研發(fā)效能任職,現(xiàn)就職于字節(jié)跳動質(zhì)量技術(shù)團(tuán)隊(duì),擔(dān)任質(zhì)量內(nèi)建智能化場景技術(shù)負(fù)責(zé)人,曾發(fā)表 4 篇國家技術(shù)專利。在質(zhì)量技術(shù)、程序分析以及智能化相關(guān)場景的應(yīng)用上有豐富的項(xiàng)目經(jīng)驗(yàn)和落地成效。


資料來源:火山引擎-開發(fā)者社區(qū)

標(biāo)題:AI 驅(qū)動的智能化單元測試生成:字節(jié)跳動的實(shí)踐與創(chuàng)新

地址:http://m.boydestruction.com//xwdt/70013.html