使用Jacoco統計服務端程式碼覆蓋情況實踐

DeepEnding發表於2021-10-05
一、背景

隨著需求的迭代,需求增加的同時,有可能會伴隨著一些功能的下線。如果不對系統已經不用的程式碼進行梳理並刪除不需要的程式碼,那麼就會增加系統維護成本以及理解成本。但經歷比較長的迭代以及系統交接,可能有些程式碼並不確定是否能夠刪除,因此基於此困境基於Jacoco對程式碼進行分析,對系統做“瘦身”。

二、原理

Jacoco本質上是一個測試覆蓋率工具,通過ASM位元組碼增強技術在原始碼中加入探針從而獲取程式碼覆蓋率,有兩個主要功能一是單測覆蓋率二是介面覆蓋率。大部分情況下我們只用於生成單測覆蓋率,而為了實現對服務端程式碼使用情況進行統計,需要使用Jacoco生成服務端的介面測試覆蓋率,即對線上對介面的每一次請求作為介面測試。此外還使用到jacoco ant,用於直接呼叫執行command line命令。

三、最佳實踐

在專案上新增Maven依賴

<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.ant</artifactId>
    <version>0.8.3</version>
</dependency>
<dependency>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant</artifactId>
     <version>1.9.9</version>
 </dependency>

新增一個url地址,用於Dump Coverage檔案即exec檔案,請求時間產生的exec檔案代表的是從啟動到dump時的所有請求覆蓋的程式碼。

@RestController
@RequestMapping("coverage")
public class CoverageController {


    @PostMapping("dump")
    public Result<Boolean> dumpCoverageFile() {
        DumpTask dumpTask = new DumpTask();
		// dump檔案儲存地址,確保有寫的許可權
        dumpTask.setDestfile(new File("/export/code-cover.exec"));
		// 多次dump追加形式
        dumpTask.setAppend(true);
		// 選一個空閒介面即可
        dumpTask.setPort(8840);
		// 預設本機tomcat
        dumpTask.setAddress("127.0.0.1");
        dumpTask.execute();
        return Result.succeed(true);
    }
}

以上為程式碼需要進行的修改。

此外包部署的環境中(伺服器)需要有jacoco的java agent包,名稱jacocoagent.jar,可以如果不好聯絡運維進行包上傳,可以直接解壓縮maven依賴中下載的包org.jacoco.agent-0.8.3.jar包含有jacocoagent.jar。解壓縮命令參考:${jarPath}為佔位符,代表org.jacoco.agent-0.8.3.jar包所在路徑

#decompress file 解壓依賴,獲得jacocoagent.jar包,避免需要聯絡運維上傳包
jar -xvf ${jarPath}

java啟動引數新增,即指定JVM相關的那個啟動引數:存在多個javaagent時,比如可能還有效能監控等等,按順序新增agent引數即可即 -javaagent:${agent1} -javaagent:...。

  • ${agentJarPath}為佔位符代表jacocoagent.jar所在路徑。

  • ${packagePath}為佔位符,代表需要統計的包路徑,可使用*進行匹配。

-javaagent:${agentJarPath}=includes=${packagePath},output=tcpserver,port=8840,address=127.0.0.1 -Xverify:none

通過url請求後可以在指定資料夾下找到對應的exec檔案然後通過運維工具或scp等進行檔案下載。

下載檔案成功後,開啟idea->run->show coverage data選擇對應的exec檔案即可獲取服務端的程式碼覆蓋情況。通過程式碼覆蓋情況可對已經不需要的程式碼進行刪除,降低維護成本。

相關文章