小架構step系列11:單元測試引入

1 概述

在還沒有寫什么代碼之前,就引入單元測試,是要強調單元測試的重要性。當一套代碼的生命周期比較長的時候,單元測試更加重要。生命周期長的代碼,不管是產品人員還是開發人員,可能都會換了一批又一批,維護才是成本的大頭。后來的人缺乏這套代碼的歷史知識,改起來就會bug頻出,質量堪憂。如果有單元測試代碼,則每次的修改如果有問題,就能夠通過單元測試代碼暴露出來,這樣改代碼會比較讓人放心。但單元測試代碼是一項做了則太平無事看不出作用的事情,但不做則經常要滅火而追悔莫及的事情。如果公司不強制要求或者工期比較緊張的,很可能是被忽略的,等到代碼積累多了、歷史知識又丟失了不少的時候,再來想補,就困難重重了。

所以,在此要先引入單元測試的基礎設施,并在寫代碼的時候都加上單元測試,以達到編寫代碼達到100%的測試覆蓋率。這個“100%”如果變成什么“80%”之類的,效果就會差很多,因為哪些測了哪些沒測就分不清楚了,就很難監督單元測試的執行了。如果實在有些是測不了的,那么應該在工具中排除掉,排除掉的代碼應該盡量少,在此基礎上保持“100%”的覆蓋率,使得能夠比較好的監督單元測試有沒有在正常執行。

2 單元測試

2.1 引入依賴

Springboot已經對測試給出了自己的推薦,也是目前比較流行的選擇,如果沒有什么特殊需求的話,直接選用即可。

首先,在<dependencies>中引入test的依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

就是這樣一個依賴,就基本足夠了。

2.2 具體依賴

找到 https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-test/2.7.18/spring-boot-starter-test-2.7.18.pom 文件,看看里面的具體依賴:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test-autoconfigure</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><version>3.22.0</version><scope>compile</scope></dependency><dependency><groupId>org.hamcrest</groupId><artifactId>hamcrest</artifactId><version>2.2</version><scope>compile</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version><scope>compile</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>4.5.1</version><scope>compile</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-junit-jupiter</artifactId><version>4.5.1</version><scope>compile</scope></dependency>
</dependencies>

上面是一些主要依賴的摘錄,前三個是引入springboot的基礎,單元測試庫junit已經是事實標準,通過junit-jupiter一起引入;斷言庫同時引入了assertj和hamcrest,它們各有各的優勢,這里優先使用assertj;mock庫則選用了mockito。mock對象,進行單元測試,最后斷言結果,這是測試的三個步驟,分別使用了對應的庫,這幾種庫的語法需要學一學。

單元測試的代碼要求邏輯簡單,就做上面三件事情,不要有什么業務邏輯,單元測試之間也不要有什么關系,保證單元測試代碼簡單,因為沒有人再來測試單元測試代碼了。

3 測試覆蓋率

單元測試是一個做了不好看到效果,如果沒有限制,那做多多少全憑開發的心情,那大概率很快就會荒廢掉。所以需要有監督方式,其中就是引入測試覆蓋率工具,這里選用JaCoCo,通過它來生成測試覆蓋率,每次寫完代碼都應該檢查測試覆蓋率,確保單元測試覆蓋所有預期的代碼。

3.1 工具引入

引入JaCoCo,只需要在pom.xml中的里增加插件,版本根據情況選比較新的:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.13</version>
</plugin>

3.2 生成測試覆蓋率

3.2.1 IDEA生成測試覆蓋率

在IDEA中,選中單元測試用例類(可以整個目錄),然后右鍵選擇菜單“Run Tests in project_name with Coverage”:

IDEA會執行對應的測試用例,如果是在測試的根目錄執行,則可以得到所有測試用例的測試覆蓋率,并把結果展示到一個“Coverage”窗口里:

針對那些覆蓋率不到100%的類進行檢查和補充測試用例,如果要看詳情則可以導出報告:

導出的報告里有個index.html,打開該文件會展示各個類的測試覆蓋率,選擇覆蓋率不到100%的類,里面是綠色的則是覆蓋的,紅色的則是未覆蓋的,針對紅色部分的代碼進行補充測試用例。

3.2.2 命令行生成測試覆蓋率

IDEA會在底下默默做一些事情,讓操作比較簡單,這對開發人員比較友好。但如果想在持續集成工具如Jenkins上也能夠生成測試覆蓋率,那么還需要增加點配置:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.13</version><executions><execution><id>prepare-agent</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>report</id><phase>test</phase><goals><goal>report</goal></goals><configuration><outputDirectory>${project.build.directory/}coverage_reports</outputDirectory></configuration></execution></executions>
</plugin>

上面<plugin>配置增加了一個<execution>,可以通過命令mvn clean test在執行測試用例的時候就把覆蓋率報告生成到coverage_reports目錄下,該目錄可以根據需要進行修改。

3.2.3 覆蓋率100%

作為開發人員,覆蓋率就應該追求覆蓋率100%。在制度上也應該這樣設定,這樣比較容易監督。實在無法測試或者沒有必要測試的則可以排除掉,排除的類也可以定期進行檢查,看看是否真的符合排除的條件。這個需要在工具上能夠檢測,使用mvn jacoco:check命令進行檢測:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.13</version><configuration><excludes><exclude>com/qqian/stepfmk/srvpro/SrvproApplication.class</exclude></excludes><rules><rule><element>PACKAGE</element><limits><limit><counter>LINE</counter><value>COVEREDRATIO</value><minimum>1</minimum></limit></limits></rule></rules></configuration><executions><execution><id>prepare-agent</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>report</id><phase>test</phase><goals><goal>report</goal></goals><configuration><outputDirectory>${project.build.directory/}coverage_reports</outputDirectory></configuration></execution><execution><id>check</id><phase>verify</phase><goals><goal>check</goal></goals></execution></executions>
</plugin>

上面配置中增加了check的<execution>節點,同時在這個插件的根里增加了配置:

1、排除掉一部分無法測試的類(可以用*、**來模糊匹配),如springboo的啟動類沒有必要進行測試;

2、增加<rules>節點指定按行(LINE)檢查覆蓋率,要達到100%。規則的配置可以參考:https://www.jacoco.org/jacoco/trunk/doc/check-mojo.html

3.2.4 黑盒測試覆蓋率

公司一般還有專門的測試部門,他們做的主要是黑盒測試。Jacoco也支持在java程序在運行的過程中收集測試覆蓋率信息,這樣就可以了解到黑盒測試到底覆蓋了哪些代碼,哪些沒有被覆蓋到。

在啟動Java程序的時候,增加一個agent服務器,用于后面dump測試覆蓋率的report:

java -jar srvpro-1.0.0-SNAPSHOT.jar -javaagent:jacocoagent.jar=excludes=com/qqian/stepfmk/srvpro/SrvproApplication.class,output=tcpserver,address=127.0.0.1,port=6300

-javaagent:jacocoagent.jar的格式為:-javaagent:[yourpath/]jacocoagent.jar=[option1]=[value1],[option2]=[value2],即其value是一個key-value對形式,用逗號分隔,key和value用等號分隔。更詳細可參考:https://www.eclemma.org/jacoco/trunk/doc/agent.html

jacocoagent.jar包下載:https://www.eclemma.org/jacoco/index.html

執行測試后,需要用cli命令先dump出數據,然后用report命令把數據轉為hmtl文件才可以看:參考https://www.jacoco.org/jacoco/trunk/doc/cli.html

# dump數據
java -jar jacococli.jar dump [--address <address>] --destfile <path> [--help] [--port <port>] [--quiet] [--reset] [--retry <count>]
例子:java -jar jacococli.jar dump --address 127.0.0.1 --port 6300 --destfile /path/jacoco.exec# 轉成report
java -jar jacococli.jar report [<execfiles> ...] --classfiles <path> [--csv <file>] [--encoding <charset>] [--help] [--html <dir>] [--name <name>] [--quiet] [--sourcefiles <path>] [--tabwith <n>] [--xml <file>]
例子:java -jar jacococli.jar report /path/jacoco.exec

4 架構一小步

1、通過spring-boot-starter-test引入測試庫junit、斷言庫assertj、mock庫mockito;

2、規范:把單元測試放到比較重要的位置,測試覆蓋率要達100%;

3、規范:單元測試代碼只做mock對象、測試業務邏輯、斷言三件事,測試代碼要保持簡單,不能有業務邏輯。

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

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

相關文章

Linux 文件共享之 HGFS 共享配置全解析

一、前言在使用 VMware 虛擬機搭建 Linux&#xff08;以 Ubuntu 為例&#xff09;環境時&#xff0c;常常需要實現主機與虛擬機之間的文件共享&#xff0c;HGFS&#xff08;VMware Host-Guest File System&#xff09;就是一種常用的文件共享方式。通過它&#xff0c;我們可以方…

模塊化設計賦能:定制組裝鋰電池設備的柔性生產解決方案

在鋰電池行業快速迭代的背景下&#xff0c;定制化需求與規模化生產之間的矛盾日益凸顯。傳統鋰電池組裝設備采用固定式架構&#xff0c;功能模塊高度耦合&#xff0c;導致設備換型周期長、兼容性差&#xff0c;難以適應電芯規格頻繁變化、工藝路線持續升級的市場需求。模塊化設…

Kubernetes 架構原理與集群環境部署

一&#xff1a;為什么需要 Kubernetes在業務開始進行容器化時&#xff0c;前期需要容器化的項目可能并不多&#xff0c;涉及的容器也并不多&#xff0c;此時基于 Docker 容器直接部署至宿主機也能實現基本的需求。但是隨著項目越來越多&#xff0c;管理的容器也會越來越多&…

JavaScript中關于環境對象的拓展

1.環境對象的定義環境對象指的是函數內的特殊變量this&#xff0c;this指向函數的調用者它代表當前函數的運行環境在平常我們判斷this經常用口訣誰調用它&#xff0c;它就指向誰&#xff0c;以下是幾種常見情況1. 在全局作用域中&#xff0c;this指向window2.在函數中&#xff…

202507中央城市工作會議

國家終于要給城市"升級系統"了&#xff01;未來城市不再拼命蓋新樓&#xff0c;而是讓現有城區更安全、舒適、智能&#xff0c;且每個城市都要找到自己的特色發展路徑 2025年7月北京“中央城市工作會議”。領導人聚在一起&#xff0c;討論“怎么把中國城市搞得更好”…

springboot如何redis鎖

如何解決超賣問題?超賣問題&#xff1a;就是多個線程并發執行&#xff0c;目前唯一方案是加鎖。如圖&#xff1a;悲觀鎖其實還有數據庫的互斥鎖。悲觀鎖是最常見的樂觀鎖實現的原理&#xff1a;版本號&#xff1a;這種方案就是&#xff1a;扣款庫存的時候首先先查詢版本號&…

minio批量刪除對象不生效

下午在寫minio上批量刪除對象的邏輯&#xff0c;各種改對象名稱&#xff0c;各種核對代碼&#xff0c;發現啥都沒錯&#xff0c;但是刪除就是不生效。 代碼如下&#xff1a; from minio.deleteobjects import DeleteObjectdelete_object_list [DeleteObject("20250626/20…

如何設計實現開發自助重啟工具-01-設計篇

自助重啟系列 如何設計實現開發自助重啟工具-01-設計篇 應用部署作業-02-流程 如何實現自助重啟-03-實現篇 開發自助重啟 說明&#xff1a;有時候研發產線需要重啟&#xff0c;為了保證安全、或者說提升效率&#xff0c;最好有一個統一的研發自助重啟頁面。 這個功能可應…

ChatTongyi × LangChain:開啟多模態AI應用創新之門

阿里云通義實驗室推出的ChatTongyi&#xff08;基于通義千問大模型&#xff09;與LangChain框架的深度集成&#xff0c;為開發者打造了一套高效、靈活、全面的AI開發工具鏈。無論是文本對話、復雜任務自動化&#xff0c;還是圖像理解&#xff0c;這一組合都為多場景智能應用的落…

Android Studio C++/JNI/Kotlin 示例 二

MainActivity.ktpackage com.demo.learn1import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivityclass MainActivity : ComponentActivity() {// 加載原生庫init {System.loadLibrary("native_code")}// 聲明原生方法// 數學…

B樹和B+樹

B樹B樹&#xff0c;?稱多路平衡查找樹&#xff0c;B樹中所被允許的孩?個數的最?值稱為B樹的階&#xff0c;通常?m表示。?棵m階B樹或為空樹&#xff0c;或為滿?如下特性的m叉樹&#xff1a; 1&#xff09;樹中每個結點?多有m棵?樹&#xff0c;即?多含有m-1個關鍵字。 2…

【版本控制】Perforce Helix Core (P4V) 完全入門指南(含虛幻引擎實戰)

目錄引言第一章&#xff1a;認識 Perforce Helix Core1.1 什么是 Perforce&#xff1f;1.2 P4V 是什么&#xff1f;1.3 核心概念速覽1.4 為什么選擇 Perforce&#xff1f;1.5 與 Git 的核心區別本章總結第二章&#xff1a;安裝與配置2.1 安裝原則&#xff1a;先服務端后客戶端2…

LlamaFactory/unsloth Demo

內部叫Tuning-Factory 參數文檔https://llamafactory.readthedocs.io/zh-cn/latest/index.html 高級技巧&#xff0c;如加速&#xff1a;https://llamafactory.readthedocs.io/zh-cn/latest/advanced/acceleration.html 0.環境 conda env list conda remove --name llm --all c…

水務工程中自動化應用:EtherNet/IP轉PROFIBUS DP連接超聲波流量計

在水務工程領域&#xff0c;自動化技術的應用愈發廣泛。隨著工業4.0概念的普及&#xff0c;不同通信協議的設備之間實現高效互聯互通變得尤為關鍵。EtherNet/IP和PROFIBUS DP作為兩種常見的工業通信協議&#xff0c;各有優勢&#xff0c;在實際應用中&#xff0c;常需要將它們進…

網絡協議和基礎通信原理

網絡協議和基礎通信原理是理解互聯網和各種網絡應用的關鍵。讓我用通俗易懂的方式&#xff0c;帶你逐一深入講解這些內容。 一、基礎概念總覽 TCP/IP協議族&#xff1a;互聯網通信的基礎&#xff0c;由一組協議組成&#xff0c;包括TCP、IP、UDP等。HTTP協議&#xff1a;基于T…

T16IZ遙控器教程__遙控器與無人機對頻

文章目錄前言一、準備設備二、對頻步驟總結前言 在使用自組PX4無人機時&#xff0c;有的小伙伴可能會遇到遙控器無法與無人機對頻連接的問題&#xff0c;別擔心&#xff0c;這篇文章會解決它。 一、準備設備 如下圖&#xff0c;無人機信號接收器&#xff0c;與無人機。 遙控器…

pyspark中map算子和flatmap算子

在 PySpark 中&#xff0c;map 和 flatMap 是兩個常用的轉換算子&#xff0c;它們都用于對 RDD&#xff08;彈性分布式數據集&#xff09;或 DataFrame 中的元素進行處理&#xff0c;但處理方式和應用場景有所不同。下面詳細講解它們的用法和適用場景。1. map 算子功能對 RDD 或…

jenkins部署前端vue項目使用Docker+Jenkinsfile方式

文章目錄前言一、前提準備二、準備構建文件三、Jenkins中構建項目總結前言 前面通過jenkinsdocker的方式部署了若依前端vue項目&#xff0c;接下來接著學習使用Jenkinsfile的方式部署前端vue項目。 一、前提準備 已經安裝好centos服務器&#xff0c;并且安裝了jenkins和docke…

Cadence操作說明

一.allegro修改絲印字體大小的方法 1.選擇Edit–>Change&#xff0c;右側彈出Options選項&#xff0c;選擇Class : New subclass Ref Des : Silkscreen_Top&#xff0c;設置Text block&#xff0c;后面的數字代表字號的大小。菜單菜單欄選擇Setup–>Design Parameters&a…

使用Stitch來生成CrypyTrack的app程序

結果&#xff1a; &#x1f9ed; 第一步&#xff1a;訪問 Stitch 平臺 打開網址&#xff1a;stitch.withgoogle.com使用你的 Google 賬號登錄&#xff0c;無需安裝任何軟件 &#x1f9f1; 第二步&#xff1a;選擇設計模式 Stitch 提供兩種模式&#xff1a; 標準模式&#xf…