北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

机器之心發表於2024-09-03
北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

AIxiv專欄是機器之心釋出學術、技術內容的欄目。過去數年,機器之心AIxiv專欄接收報導了2000多篇內容,覆蓋全球各大高校與企業的頂級實驗室,有效促進了學術交流與傳播。如果您有優秀的工作想要分享,歡迎投稿或者聯絡報導。投稿郵箱:liyazhou@jiqizhixin.com;zhaoyunfeng@jiqizhixin.com


單元測試是軟體開發流程中的一個關鍵環節,主要用於驗證軟體中的最小可測試單元,函式或模組是否按預期工作。單元測試的目標是確保每個獨立的程式碼片段都能正確執行其功能,對於提高軟體質量和開發效率具有重要意義。

然而,大模型自身無力為複雜待測函式(環複雜度大於 10)生成高覆蓋率的測試樣例集。為了解決該痛點,北京大學李戈教授團隊提出一種全新的提升測試用例覆蓋率的方法,該方法藉助程式分片思想(Method Slicing),將複雜待測函式依據語義拆解為若干簡單片段,進而讓大模型為各個簡單片段分別生成測試樣例。生成單個測試樣例時,大模型只需分析原待測函式的一個片段,分析難度減小,生成覆蓋該片段的單元測試難度隨之減小。由此推廣,提升整體測試樣例集程式碼覆蓋率。

相關論文《HITS: High-coverage LLM-based Unit Test Generation via Method Slicing》近期被 ASE 2024(at the 39th IEEE/ACM International Conference on Automated Software Engineering)頂會接受。

北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

論文地址:https://www.arxiv.org/pdf/2408.11324

接下來看看北大團隊論文研究的具體內容:

HITS 使用大模型進行程式分片

程式分片指將一個程式依據語義劃分為若干解決問題的階段。程式是對一個問題解決方案的形式化表述。一個問題解決方案通常包含多個步驟,每個步驟對應著程式中的一片(slice)程式碼。如下圖所示,一個色塊對應著一片程式碼,也對應著一個問題解決的步驟。

北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

HITS 要求大模型分別為每個程式碼片設計可以高效覆蓋它的單元測試程式碼。以上圖為例,當我們得到如圖的分片後,HITS 要求大模型為 Slice 1(綠色),Slice 2(藍色),Slice 3(紅色)分別生成測試樣例。為 Slice 1 生成的測試樣例要儘可能覆蓋 Slice 1,不用考慮 Slice 2 和 Slice 3,其餘程式碼片同理。

HITS 起效的原因有二。其一,大模型要考慮覆蓋的程式碼量降低。以上圖為例,為 Slice 3 生成測試樣例,則只需考慮 Slice 3 中的條件分支。要覆蓋 Slice 3 中的某些條件分支,只需在 Slice 1 和 Slice 2 中找尋一條執行路徑即可,無需考慮該執行路徑對 Slice 1 和 Slice 2 覆蓋率的影響。其二,依據語義(問題解決步驟)分割的程式碼片有助於大模型掌握程式碼執行中間狀態。為順序靠後的程式碼塊生成測試樣例,需要考慮先前程式碼對程式狀態的改變。由於程式碼塊依據實際問題解決步驟分割,因此可以用自然語言對先前程式碼塊的操作進行描述(如上圖中註釋部分)。由於當前大語言模型多為自然語言與程式語言混合訓練產物,良好的自然語言概括可幫助大模型更精準掌握程式碼對程式狀態的改變。

HITS 使用大模型進行程式分片。問題的解決步驟通常為帶有程式設計師主觀色彩的自然語言表述,因而可以直接利用自然語言處理能力超群的大模型。具體而言,HITS 使用上下文學習方法(In-context learning) 呼叫大模型。團隊利用過往在真實場景實踐的經驗,手工編寫若干程式分片樣例,經若干次調整後使大模型對程式分片的效果達到了研究團隊的預期。

對程式碼片生成測試樣例

給定要覆蓋的程式碼片段,要生成對應測試樣例,需經歷以下 3 個步驟:1. 對片段的輸入進行分析;2. 構造 prompt 指示大模型生成初始測試樣例;3. 使用規則後處理和大模型 self-debug 調整測試樣例使之可以正確執行。

對片段的輸入進行分析,指提取要覆蓋的片段所接受的一切外部輸入,以備後續 prompt 使用。外部輸入,指該片段所應用到的先前片段定義的區域性變數,待測方法的形參,片段內呼叫的方法以及外部變數。外部輸入的值直接決定了要覆蓋的片段的執行情況,因此將該資訊提取出來提示給大模型有助於有針對性地設計測試樣例。研究團隊在實驗中發現大模型擁有良好的提取外部輸入的能力,因此在 HITS 中由大模型來完成該任務。

接下來,HITS 構建思維鏈(Chain-of-thought)形式的 prompt 引導大模型生成測試樣例。推理步驟如下。第一步,給定外部輸入,分析要滿足待覆蓋程式碼片內的各種條件分支的排列組合,外部輸入都分別需要滿足哪些性質,如:組合 1,字串 a 需要包含字元’x’,整數變數 i 需要非負;組合 2,字串 a 需要非空,整數變數 i 需要為質數。第二步,對上一步中的每一種組合,分析相對應的待測程式碼執行時所處環境的性質,包括但不限於實參的特性,全域性變數的設定。第三步,為每一種組合生成一個測試樣例。研究團隊為每一步手工構建了樣例,以便於大模型能夠正確理解並執行指令。

最後,HITS 透過後處理和 self-debug 使大模型生成的測試樣例得以正確執行。大模型生成的測試樣例往往難以直接使用,會出現各式各樣的編譯錯誤和來自於錯誤編寫測試樣例導致的執行時錯誤。研究團隊根據自身觀察及已有論文的總結,設計了若干規則和常見錯誤的修復案例。首先嚐試依據規則修復。如果規則無法修復,則使用大模型 self-debug 的功能進行修復,在 prompt 中提供了常見錯誤的修復案例以供大模型參考。

北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

HITS 的整體圖解

實驗驗證

研究團隊使用 gpt-3.5-turbo 作為 HITS 呼叫的大模型,分別在大模型學習過和未學習過的 Java 專案中的複雜函式(環複雜度大於 10)上對比 HITS,其他基於大模型的單元測試方法和 evosuite 的程式碼覆蓋率。實驗結果顯示 HITS 相較於被比較的諸方法有較明顯的效能提升。

北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

北大李戈團隊提出大模型單測生成新方法,顯著提升程式碼測試覆蓋率

研究團隊透過樣例分析展示分片方法如何提升程式碼覆蓋率。如圖所示。

該案例中,基線方法生成的測試樣例未能完全覆蓋 Slice 2 中的紅色程式碼片段。然而,HITS 由於聚焦於 Slice 2,對其所引用的外部變數進行了分析,捕捉到 “如果要覆蓋紅色程式碼片段,變數’arguments’ 需要非空 “的性質,根據該性質構建了測試樣例,成功實現了對紅色區域程式碼的覆蓋。

提升單元測試覆蓋率,增強系統的可靠性和穩定性,進而提高軟體質量。HITS使用程式分片實驗證明,該技術不僅能大幅提升整體測試樣例集程式碼覆蓋率,且實施方法簡潔直接,未來有望在真實場景實踐中,幫助團隊更早發現並修正開發中的錯誤,提升軟體交付質量。

相關文章