引言
在軟體開發這一充滿創造性的領域中,開發人員不僅要構建功能強大的軟體,還要確保這些軟體的穩定性和可靠性。然而,開發過程中並非所有任務都能激發創造力,有些甚至是重複且乏味的。其中,編寫單元測試無疑是最令人頭疼的任務之一,它雖然對於驗證軟體元件是否按預期工作至關重要,但其編寫過程卻常常讓開發人員感到枯燥和疲憊。理想的情況是,開發人員在編寫程式碼的同時編寫單元測試。但是編寫單元測試是軟體開發中的繁瑣工作,會佔用開發人員大量時間。並且開發人員在手動編寫複雜程式碼庫的單元測試時可能會犯錯。因此,很多軟體缺乏足夠的單元測試,這使得程式碼難以維護。如果沒有單元測試,出現問題後定位問題就如同大海撈針,這不僅增加了維護成本,也降低了軟體的可靠性。
在這樣的背景下,AI 程式碼助手應運而生,它透過大模型輔助生成程式碼來減輕開發人員在單元測試編寫上的負擔,提高開發效率,同時確保軟體質量。它將如何幫助開發人員克服單元測試的挑戰,是我們接下來要探討的主題。
一、 單元測試概述
單元測試專注於程式中的最小可測試單元,這通常包括函式、類的方法或模組等。其核心目的是確保這些基本單元能夠正確執行特定的功能,並妥善處理各種邊界條件和異常情況。單元測試的目的是確保這些基本組成單元按照預期工作,能夠正確地執行特定的功能,並且能夠妥善處理各種邊界條件和異常情況。
單元測試一般情況下需要符合如下特點:
- 自動化:單元測試由開發人員編寫,並使用自動化測試框架執行,能夠快速反饋測試結果,提高測試效率。
- 隔離性:每個單元測試獨立執行,將被測試單元與其他程式碼隔離,確保測試的準確性和可靠性。
- 針對性:每個測試用例都針對程式碼中一個具體的、明確的行為,確保測試的精確性和有效性。
- 重複性:單元測試可以頻繁重複執行,尤其是在程式碼修改後,以確保新修改沒有引入錯誤。
- 及時反饋:單元測試能夠快速發現錯誤並定位問題,提高開發效率和軟體質量。
單元測試一般會包含以下型別:
- 函式測試:驗證函式或方法在給定輸入下是否返回預期的輸出。這包括測試各種正常的輸入值,以確保函式按照預期工作
- 邊界條件測試:測試函式或方法在輸入值達到邊界或極限情況下的行為。例如,對於一個接受整數輸入的函式,邊界條件測試應該包括測試最小值、最大值、以及接近最小值和最大值的數值。這可以幫助發現函式在處理極端情況時的錯誤
- 異常處理測試:測試函式或方法在遇到異常情況(例如無效輸入、錯誤引數或資源不足)時的行為。這包括測試函式是否能夠正確地處理異常,並返回適當的錯誤資訊或採取相應的補救措施
- Mock 測試:使用模擬物件來代替真實的依賴項(例如資料庫連線或外部API),從而隔離被測單元,並確保測試結果的可靠性。這對於測試依賴於外部資源的函式或方法非常有用,因為它可以避免測試結果受到外部因素的影響
- 資料驅動測試:使用一個資料表來驅動測試用例的執行。測試用例的輸入資料和預期輸出資料都儲存在資料表中,測試程式會讀取資料表中的資料,並自動執行測試用例。這可以減少測試程式碼的冗餘,並提高測試效率,尤其是在需要測試大量不同輸入值的情況下
在實際的開發場景中,需要結合業務的真實需求,選擇合適的測試型別,來確保程式碼質量和功能正確性。
二、 AI 在單元測試中的應用
騰訊雲 AI 程式碼助手是騰訊雲自研的一款開發程式設計提效輔助工具,它透過外掛的方式整合到編輯器中,輔助程式設計工作。這款工具能夠在開發人員編寫程式碼的同時提供智慧建議,自動生成程式碼片段,甚至可以根據函式生成對應的單元測試。以下是騰訊雲 AI 程式碼助手在單元測試中的應用實踐:
程式碼補全與單元測試生成: 騰訊雲 AI 程式碼助手基於上下文理解,能夠自動推薦最可能的程式碼片段,包括方法呼叫、變數宣告、迴圈結構等。此外,它還能根據現有程式碼結構,自動生成對應的單元測試案例,確保程式碼變更時功能的穩定性。
可以透過對話方塊中的 /test 生成單元測試,或者使用 IDE 編碼區域中使用每個功能方法的快捷鍵“生成測試”來生成該方法的單元測試。
多輪對話最佳化測試用例: 開發者可以透過多輪對話,告訴 AI 更多的資訊,讓生成的單元測試內容更符合業務預期。例如,可以指定業務邊界條件、特殊的異常處理邏輯、資料處理方式等。
對於生成的內容,如果有額外的測試場景需求,可以透過對論對話追加提問。
AI 程式碼助手的對話模型會識別使用者意圖結合上下文對話內容最佳化單元測試結果。
一鍵應用單元測試內容: 透過對話方塊結果中的快捷按鈕,如“應用”、“插入到 IDE”等,開發者可以快速判斷與接受生成的單元測試程式碼。
可以選擇“應用”按鈕,將對話生成的結果,作用到對應的程式碼檔案中。
可以在 IDE 編碼區域看到“應用”這部分程式碼對於當前程式碼檔案的修改情況,讓研發人員快速識別到改動,快速判斷與接受。
透過這些應用功能,我們可以看到騰訊雲 AI 程式碼助手在單元測試中的強大能力,它不僅提高了開發效率,還幫助確保了軟體的質量和穩定性。
三、實際編碼案例解析
針對業務程式碼準確生成單元測試
在真實的開發場景中,軟體的功能都是異常複雜的,一個完整的軟體功能有多個類、方法共同組成。以 Java 開發為例,一個功能的開發,可能由 類的定義、Controller 控制層的方法、Server 介面定義、ServiceImpl 介面實現類方法、Repository 和 DTO 等等部分組成。在生成單元測試的時候,需要考慮到真實業務中的各個元件關聯性。
以上圖這個 Java 工程為例,我們需要 AI 幫我們準確生成介面實現類 EstateServiceImpl.java 中的查詢和模糊查詢方法對應的單元測試程式碼。
我們選中 getEstates 和 getEstatesContainingText 方法之後,使用 /test 為其生成單元測試程式碼。在結果中可以看到,騰訊雲 AI 程式碼助手在生成單元測試的時候,會分析程式碼的工程結構,並在生成的時候智慧 import 相關依賴;在生成測試程式碼的時候,會結合其他檔案中的類和方法定義生成測試計劃,並準確構造測試資料。
將生成的單元測試內容,插入到指定單元測試檔案中,可以直接執行 mvn test 命令進行單元測試驗證,可以看到這裡生成的程式碼可以編譯透過,並完成單元測試功能
結合業務邏輯逐步完善測試結果
在真實的業務開發過程中,有很多測試場景都是隱晦的,它的邏輯可能並沒有直接定義在程式碼內容中,而是需要結合實際需求而定。這種場景下,需要研發人員使用對話功能告訴 AI 程式碼助手這裡的業務測試邏輯,繼而完善測試程式碼。
如上圖所示,我們可以透過多輪對話能力,繼續輸入真實業務場景,豐富測試的邊界條件,讓 AI 持續最佳化單元測試結果。
我們將生成的擴充套件內容應用到之前的單元測試程式碼中,並執行下這裡生成的最終結果,可以看到執行成功。
四、AI 單元測試的優勢
從上文的實際單元測試生成場景中可以看到,騰訊雲 AI 程式碼助手可以準確的生成單元測試程式碼,在技術上,騰訊雲 AI 程式碼助手採用了兩個核心優勢技術,讓生成的單元測試結果更準確。
應用上採用 AST 語法樹解析技術,讓 AI 更理解專案工程,生成結果更符合業務邏輯
在單元測試過程中,最小可測試的工作單元一般為 函式、方法、類、介面等,工作單元的結果包含:返回值、系統狀態更改、呼叫第三方服務。一般情況下,工作單元的結果為以上三種的一種,或者三種的組合。
在實際的專案中,我們的測試單元很可能存在對外部的依賴,而單元測試的獨立性原則要求測試用例應該要獨立執行的,即我們只需要保證被測試的單元內部邏輯正確即可,不需要真正依賴外部資源,因此我們最重要的事情是識別依賴。
騰訊雲 AI 程式碼助手,透過 AST 語法樹解析技術,在生成單元測試的時候,不單單隻將單元測試的功能程式碼給到模型,還會結合 AST 獲取功能程式碼背後的依賴程式碼,比如檔案I/O操作、HTTP介面呼叫、RPC呼叫、對資料庫或者訊息佇列等資源的請求程式碼。將這些依賴程式碼給到大模型,可以有效理解軟體工程的業務邏輯,也可以結合這些依賴程式碼,在生成單元測試的時候,自動生成準確有效的Mock、stub、fake 等資料。模型上針對各類主流的單元測試框架進行了增量訓練,可自動識別各類主流單測框架
在單元測試場景下,各主流的編碼語言都有對應的單元測試框架,不通框架的單元測試程式碼邏輯有一定區別。騰訊雲 AI 程式碼助手,支援根據現有單元測試程式碼自動識別對應的單元測試框架,在生成的時候可以遵循當前專案已有框架生成。同時,騰訊雲 AI 程式碼助手也針對業界主流的單元測試框架進行了增量訓練,最佳化單元測試的生成效果。
五、未來展望
雖然騰訊雲 AI 程式碼助手目前可以做到針對單個方法/單個檔案的單元測試生成,但還是依賴研發人員的對於此功能的主動使用與探索,並且當前 AI 生成程式碼還存在一些侷限性:
只能做到片段式生成,多個程式碼檔案之間需要聯動測試的場景,覆蓋度一般
生成結果比較比較隨機,多次執行的結果可能差異較大
騰訊雲 AI 程式碼助手即將推出批次單元測試執行能力,旨在幫助開發者以最小成本有效提升單測覆蓋率。
專案級別的批次單元測試生成,需要強大的基礎模型能力,包括:支援豐富的上下文、模型對於程式碼工程的理解和推理能力、模型的反思能力等;同時對於業務程式碼本身需要非常標準規範,註釋清晰、邏輯明確。程式碼解耦較好,程式碼可測性較強。單元測試最終仍需要技術人員進行確認,研發需要理解模型生成的單測結果,並配合模型不斷提升單測效率。
六、總結
總結來說,騰訊雲 AI 程式碼助手結合騰訊混元大模型的功能,已經在單元測試領域展現出了顯著的價值,它不僅提高了開發效率,還幫助確保了軟體的質量和穩定性。隨著技術的不斷進步,AI 在單元測試中的應用將更加廣泛和深入,為軟體開發帶來更多的便利和創新。