如何提高單元測試的覆蓋率

一、定位未覆蓋的代碼

  1. ?利用 IDEA 的覆蓋率工具?:

    • 右鍵測試類 → ?Run with Coverage,或使用?Alt+Shift+F10(Windows)打開運行菜單選擇覆蓋率。
    • ?查看高亮標記?:
      • ?綠色?:已覆蓋代碼行。
      • ?紅色?:未覆蓋代碼行。
      • ?黃色?:部分覆蓋(如條件分支未完全覆蓋)。

    https://via.placeholder.com/600x400?text=IDEA+Coverage+Highlight

  2. ?分析 JaCoCo 報告?:

    • 打開?target/site/jacoco/index.html,查看:
      • ?行覆蓋率?(Line):哪些行未執行?
      • ?分支覆蓋率?(Branch):哪些條件分支(如?if/else)未覆蓋?
      • ?方法覆蓋率?:是否有未調用的方法?

二、針對性提升覆蓋率的策略

策略 1:覆蓋邊界條件
  • ?示例場景?:一個計算器類的方法?divide(int a, int b)
    public int divide(int a, int b) {if (b == 0) throw new IllegalArgumentException("除數不能為0");return a / b;
    }
  • ?問題?:常規測試可能只覆蓋?b≠0?的情況,遺漏了異常分支。
  • ?解決方案?:
    @Test
    void testDivideByZero() {Calculator calculator = new Calculator();assertThrows(IllegalArgumentException.class, () -> calculator.divide(5, 0));
    }
策略 2:覆蓋所有代碼分支
  • ?示例場景?:帶有?if-else?的邏輯。
    public String getGrade(int score) {if (score >= 90) return "A";else if (score >= 60) return "B";else return "C";
    }
  • ?問題?:若僅測試?score=80,則未覆蓋?score≥90?和?score<60?的分支。
  • ?解決方案?:使用參數化測試覆蓋所有分支:
    @ParameterizedTest
    @CsvSource({"95, A", "75, B", "50, C"})
    void testGetGrade(int score, String expected) {assertEquals(expected, grader.getGrade(score));
    }
策略 3:覆蓋異常和錯誤處理
  • ?示例場景?:數據庫操作失敗時的回滾邏輯。
    public void saveData(Data data) {try {database.insert(data);} catch (SQLException e) {logger.error("保存失敗", e);rollback();}
    }
  • ?問題?:正常流程測試不會觸發?catch?塊。
  • ?解決方案?:使用 Mockito 模擬異常:
    @Test
    void testSaveDataFailure() {Database mockDb = mock(Database.class);when(mockDb.insert(any())).thenThrow(new SQLException());DataService service = new DataService(mockDb);service.saveData(new Data());verify(mockDb).rollback(); // 驗證是否執行了回滾
    }
策略 4:覆蓋工具生成的代碼
  • ?常見問題?:Lombok 生成的?getter/setterequals/hashCode?或 IDE 自動生成的代碼未覆蓋。
  • ?解決方案?:
    • 顯式測試生成的代碼(如驗證?equals?方法)。
    • 配置 JaCoCo 忽略 Lombok 生成的代碼(在?pom.xml?中):
      <configuration><excludes><exclude>?**?/*$Lombok*/?**?</exclude></excludes>
      </configuration>

三、高級技巧

技巧 1:強制覆蓋難以觸發的代碼
  • ?場景?:測試?private?方法或靜態代碼塊。
    public class ConfigLoader {static {loadConfig(); // 靜態代碼塊}private static void loadConfig() { /* 加載配置 */ }
    }
  • ?解決方案?:通過反射調用私有方法或觸發靜態初始化:
    @Test
    void testStaticBlock() throws Exception {Class.forName("com.example.ConfigLoader"); // 觸發靜態代碼塊
    }
技巧 2:優化測試數據
  • ?使用隨機測試工具?:如?QuickTheories?或?jqwik,生成大量隨機輸入覆蓋邊緣情況。
    @Property
    void testRandomInput(@ForAll int a, @ForAll int b) {assumeTrue(b != 0); // 忽略 b=0 的情況assertEquals(a / b, calculator.divide(a, b));
    }
技巧 3:忽略無需覆蓋的代碼
  • ?配置 JaCoCo 排除?(在?pom.xml?中):
    <excludes><exclude>?**?/model/*.java</exclude> // 忽略 POJO 類<exclude>?**?/Main.java</exclude>    // 忽略啟動類
    </excludes>

四、避免常見誤區

  1. ?盲目追求 100% 覆蓋率?:

    • 某些代碼(如自動生成的代碼、簡單 Getter)無需強制覆蓋。
    • 更關注核心邏輯和復雜分支的覆蓋。
  2. ?編寫無效測試?:

    @Test
    void testAdd() {calculator.add(2, 3); // 沒有斷言!看似覆蓋,實則無效
    }
  3. ?忽略測試代碼質量?:

    • 避免重復代碼:用?@BeforeEach?初始化公共對象。
    • 遵循命名規范:測試方法名應明確表達場景(如?testDivide_WhenDivisorIsZero_ThrowException)。

五、總結

通過以下步驟系統提升覆蓋率:

  1. ?定位未覆蓋代碼?:使用 IDEA 高亮和 JaCoCo 報告。
  2. ?設計針對性用例?:覆蓋邊界條件、異常分支、復雜邏輯。
  3. ?利用工具和技巧?:參數化測試、Mock 異常、反射調用。
  4. ?平衡覆蓋率和成本?:優先覆蓋關鍵代碼,忽略無關部分。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76242.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76242.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76242.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

聚合直播-Simple Live-v1.7.7-全網直播平臺能在一個軟件上看完

聚合直播-Simple Live 鏈接&#xff1a;https://pan.xunlei.com/s/VOO7u3o4FNL_XA9VJ6l7KBNfA1?pwdyrau# 聚合直播-Simple Live-v1.7.7-全網直播平臺能在一個軟件上看完

三大等待和三大切換

三大等待 1、三大等待&#xff1a;等待的方式有三種&#xff1a;強制等待&#xff0c;隱性等待&#xff0c;顯性等待。 1、強制等待&#xff1a;time.sleep(2)&#xff0c;秒 優點&#xff1a;使用簡單缺點&#xff1a;等待時間把握不準&#xff0c;容易造成時間浪費或者等待時…

使用Lombok @Builder 收參報錯提示沒有無參構造方法的原因與解決辦法

使用Lombok Builder 收參報錯提示沒有無參構造方法的原因與解決辦法 類上加了Builder之后接口接收前端傳來的參數報錯&#xff1a;(no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) 1.解決辦法…

SAP 查找JOB進程ID

如何查找后臺JOB的進程ID SM37勾選對于JOB

通過C# 將Excel表格轉換為圖片(JPG/ PNG)

Excel 表格可能會因為不同設備、不同軟件版本或字體缺失等問題&#xff0c;導致格式錯亂或數據顯示異常。轉換為圖片后&#xff0c;能確保數據的排版、格式和外觀始終保持一致&#xff0c;無論在何種設備或平臺上查看&#xff0c;都能呈現出固定的樣式&#xff0c;避免了因環境…

Langchain構建RAG對話應用

本文&#xff1a;關注 檢索器與上下文的子鏈、父鏈&#xff1b;即檢索器也需要上下文內容。 RAG是一種增強LLM知識的方法&#xff0c;通過引入額外的數據來實現。 實現思路&#xff1a;加載—》分割—》存儲—》檢索—》生成。 初始化 import os import bs4 from langchain.c…

關于模擬噪聲分析的11個誤區

目錄 1. 降低電路中的電阻值總是能改善噪聲性能 2. 所有噪聲源的噪聲頻譜密度可以相加&#xff0c;帶寬可以在最后計算時加以考慮 3. 手工計算時必須包括每一個噪聲源 4. 應挑選噪聲為ADC 1/10的ADC驅動器 5. 直流耦合電路中必須始終考慮1/f噪聲 6. 因為1/f噪聲隨著頻率降…

vue,uniapp解決h5跨域問題

如果有這樣的跨域問題&#xff0c;解決辦法&#xff1a; ? 第一步&#xff1a;在項目根目錄下創建 vue.config.js 和 package.json 同級目錄。 // vue.config.js module.exports {devServer: {proxy: {/api: {target: https://app.yycjkb.cn, // 你的后端接口地址changeOrig…

SQL通用語法和注釋,SQL語句分類(DDL,DML,DQL,DCL)及案例

目錄 SQL通用語法和注釋 SQL語句分類&#xff08;DDL&#xff0c;DML&#xff0c;DQL&#xff0c;DCL&#xff0c;TPL&#xff0c;CCL&#xff09; DDL&#xff08;數據定義語言&#xff09; 數據庫操作 查詢&#xff08;SHOW、SELECT&#xff09; 創建&#xff08;CREAT…

Linux:線程概念與控制

??所屬專欄&#xff1a;Linux?? ??作者主頁&#xff1a;嶔某?? Linux&#xff1a;線程概念于控制 var code “d7e241ae-ed4d-475f-aa3d-8d78f873fdca” 概念 在一個程序里的一個執行路線就叫做線程thread。更準確一點&#xff1a;線程是“一個進程內部的控制序列” …

人臉識別聯合行為檢測的辦公管理新模式

基于人臉識別與行為檢測的辦公智能化解決方案 一、背景 在傳統辦公場景中&#xff0c;員工考勤管理、工位使用情況統計、安全監控等環節存在諸多痛點。例如&#xff0c;傳統考勤方式如指紋打卡、刷卡等存在代打卡現象&#xff0c;考勤數據不準確&#xff1b;對于員工是否在工…

ceph weight 和 reweight 的區別

ceph osd df ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS0 nvme 6.98630 0.95508 7.0 TiB 5.0 TiB 4.9 TiB 13 GiB 33 GiB 2.0 TiB 71.10 0.96 83 up1 nvme 6.98630

WInform當今技術特性分析

Windows Forms (WinForms) 技術特性分析 引言 Windows Forms (WinForms) 作為微軟最早推出的基于.NET的圖形用戶界面開發框架&#xff0c;已經存在了20多年。在如今充滿了各種現代UI框架的軟件開發生態系統中&#xff0c;WinForms仍然保持著其獨特的地位。本文將深入分析WinF…

Spark rdd算子解析與實踐

一、RDD基礎回顧 RDD&#xff08;Resilient Distributed Dataset&#xff09; 是Spark的核心抽象&#xff0c;代表一個不可變、分區的分布式數據集合。其核心特性包括&#xff1a; 容錯性&#xff1a;通過血緣&#xff08;Lineage&#xff09;記錄數據生成過程&#xff0c;支…

sqlite3的API以及命令行

sqlite是目前最流行的嵌入式數據庫。 所謂嵌入式&#xff0c;就是足夠簡單&#xff0c;可以嵌入到我們自己開發的應用程序之中。 在Linux系統中&#xff0c;sqlite的使用只需要使用它的API&#xff0c;連接它的動態連接庫&#xff0c;甚至都不用連接&#xff0c;sqlite的實現…

Allure測試報告按測試終端和測試類型智能分類查看

以下是實現Allure測試報告按測試終端和測試類型智能分類的完整方案: 一、測試框架分層設計 # 項目結構 project/ ├── api_tests/ # API測試 │ └── test_order.py ├── app_tests/ # 移動端測試 │ ├── android/ │ └── ios/ ├── pc_te…

Spine-Leaf 與 傳統三層架構:全面對比與解析

本文將詳細介紹Spine-Leaf架構&#xff0c;深入對比傳統三層架構&#xff08;Core、Aggre、Access&#xff09;&#xff0c;并探討其與Full-mesh網絡和軟件定義網絡&#xff08;SDN&#xff09;的關聯。通過通俗易懂的示例和數據中心網絡分析&#xff0c;我將幫助您理解Spine-L…

圖像預處理-圖像噪點消除

一.基本介紹 噪聲&#xff1a;指圖像中的一些干擾因素&#xff0c;也可以理解為有那么一些點的像素值與周圍的像素值格格不入。常見的噪聲類型包括高斯噪聲和椒鹽噪聲。 濾波器&#xff1a;也可以叫做卷積核 - 低通濾波器是模糊&#xff0c;高通濾波器是銳化 - 低通濾波器就…

安卓手機如何改ip地址教程

對于安卓手機用戶而言&#xff0c;ip修改用在電商、跨境電商、游戲搬磚、社交軟件這些需要開多個賬號的項目。因為多個設備或賬號又不能在同一ip網絡下&#xff0c;所以修改手機的IP地址防檢測成為一個必要的操作。以下是在安卓手機上更改IP地址的多種方法及詳細步驟&#xff0…

對象池模式在uniapp鴻蒙APP中的深度應用

文章目錄 對象池模式在uniapp鴻蒙APP中的深度應用指南一、對象池模式核心概念1.1 什么是對象池模式&#xff1f;1.2 為什么在鴻蒙APP中需要對象池&#xff1f;1.3 性能對比數據 二、uniapp中的對象池完整實現2.1 基礎對象池實現2.1.1 核心代碼結構2.1.2 在Vue組件中的應用 2.2 …