国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

為什么程序員一定要寫單元測試?

2023-11-15 15:39 作者:程序員魚皮  | 我要投稿

大家好,我是魚皮,很多初學編程的同學都會認為 “程序員的工作只有開發(fā)新功能,功能做完了就完事兒”。但其實不然,保證程序的正常運行、提高程序的穩(wěn)定性和質(zhì)量也是程序員的核心工作。

之前給大家分享過企業(yè)項目的完整開發(fā)流程,其中有一個關(guān)鍵步驟叫 “單元測試”,這篇文章就來聊聊程序員如何編寫單元測試吧。

什么是單元測試?

單元測試(Unit Testing,簡稱 UT)是軟件測試的一種,通常由開發(fā)者編寫測試代碼并運行。相比于其他的測試類型(比如系統(tǒng)測試、驗收測試),它關(guān)注的是軟件的 最小 可測試單元。

什么意思呢?

假如我們要實現(xiàn)用戶注冊功能,可能包含很多個子步驟,比如:

  1. 校驗用戶輸入是否合法

  2. 校驗用戶是否已注冊

  3. 向數(shù)據(jù)庫中添加新用戶

其中,每個子步驟可能都是一個小方法。如果我們要保證用戶注冊功能的正確可用,那么就不能只測試注冊成功的情況,而是要盡量將每個子步驟都覆蓋到,分別針對每個小方法做測試。比如輸入各種不同的賬號密碼組合來驗證 “校驗用戶輸入是否合法” 這一步驟在成功和失敗時的表現(xiàn)是否符合預期。

同理,如果我們要開發(fā)一個很復雜的系統(tǒng),可能包含很多小功能,每個小功能都是一個單獨的類,我們也需要針對每個類編寫單元測試。因為只有保證每個小功能都是正確的,整個復雜的系統(tǒng)才能正確運行。

單元測試的幾個核心要點是:

  1. 最小化測試范圍:單元測試通常只測試代碼的一個非常小的部分,以確保測試的簡單和準確。

  2. 自動化:單元測試應該是自動化的,開發(fā)人員可以隨時運行它們來驗證代碼的正確性,特別是在修改代碼后。而不是每次都需要人工去檢查。

  3. 快速執(zhí)行:每個單元測試的執(zhí)行時間不能過長,應該盡量做到輕量、有利于頻繁執(zhí)行。

  4. 獨立性:每個單元測試應該獨立于其他測試,不依賴于外部系統(tǒng)或狀態(tài),以確保測試的可靠性和可重復性。

為什么需要單元測試?

通過編寫和運行單元測試,開發(fā)者能夠快速驗證代碼的各個部分是否按照預期工作,有利于保證系統(tǒng)功能的正確可用,這是單元測試的核心作用。

此外,單元測試還有很多好處,比如:

1)改進代碼:編寫單元測試的過程中,開發(fā)者能夠再次審視業(yè)務流程和功能的實現(xiàn),更容易發(fā)現(xiàn)一些代碼上的問題。比如將復雜的模塊進一步拆解為可測試的單元。

2)利于重構(gòu):如果已經(jīng)編寫了一套可自動執(zhí)行的單元測試代碼,那么每次修改代碼或重構(gòu)后,只需要再自動執(zhí)行一遍單元測試,就知道修改是否正確了,能夠大幅提高效率和項目穩(wěn)定性。

3)文檔沉淀:編寫詳細的單元測試本身也可以作為一種文檔,說明代碼的預期行為。

魚皮以自己的一個實際開發(fā)工作來舉例單元測試的重要性。我曾經(jīng)編寫過一個 SQL 語法解析模塊,需要將 10000 多條鏈式調(diào)用的語法轉(zhuǎn)換成標準的 SQL 語句。但由于細節(jié)很多,每次改進算法后,我都不能保證轉(zhuǎn)換 100% 正確,總會人工發(fā)現(xiàn)那么幾個錯誤。所以我編寫了一個單元測試來自動驗證解析是否正確,每次改完代碼后執(zhí)行一次,就知道解析是否完全成功了。大幅提高效率。

所以無論是后端還是前端程序員,都建議把編寫單元測試當做一種習慣,真的能夠有效提升自己的編碼質(zhì)量。

如何編寫單元測試?

以 Java 開發(fā)為例,我們來學習如何編寫單元測試。

Java 開發(fā)中,最流行的單元測試框架當屬 JUnit 了,它提供了一系列的類和方法,可以幫助我們快速檢驗代碼的行為。

1、引入 JUnit

首先我們要在項目中引入 JUnit,演示 2 種方式:

Maven 項目引入

在 pom.xml 文件中引入 JUnit 4 的依賴:

<dependency>
????<groupId>junit</groupId>
????<artifactId>junit</artifactId>
????<version>4.13.2</version>
????<scope>test</scope>
</dependency>

Spring Boot 項目引入

如果在 Spring Boot 中使用 JUnit 單元測試,直接引入 spring-boot-starter-test 包即可:

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

然后會自動引入 JUnit Jupiter,它是 JUnit 5(新版本)的一部分,提供了全新的編寫和執(zhí)行單元測試的方式,更靈活易用。不過學習成本極低,會用 JUnit 4,基本就會用 JUnit Jupiter。

2、編寫單元測試

編寫一個單元測試通常包括三個步驟:準備測試數(shù)據(jù)、執(zhí)行要測試的代碼、驗證結(jié)果。

一般來說,每個類對應一個單元測試類,每個方法對應一個單元測試方法。

編寫 JUnit 單元測試

比如我們要測試一個計算器的求和功能,示例代碼如下:

import?org.junit.Test;
import?org.junit.Assert;

public?class?CalculatorTest?{

????//?通過?Test?注解標識測試方法
????@Test
????public?void?testAdd()?{
????????//?準備測試數(shù)據(jù)
????????long?a?=?2;
????????long?b?=?3;
????????
????????//?執(zhí)行要測試的代碼
????????Calculator?calculator?=?new?Calculator();
????????int?result?=?calculator.add(2,?3);
????????
????????//?驗證結(jié)果
????????Assert.assertEquals(5,?result);
????}
}

上述代碼中的 Assert 類是關(guān)鍵,提供了很多斷言方法,比如 assertEquals(是否相等)、assertNull(是否為空)等,用來對比程序?qū)嶋H輸出的值和我們預期的值是否一致。

如果結(jié)果正確,會看到如下輸出:

如果結(jié)果錯誤,輸出如下,能夠清晰地看到執(zhí)行結(jié)果的差異:

Spring Boot 項目單測

如果是 Spring Boot 項目,我們經(jīng)常需要對 Mapper 和 Service Bean 進行測試,則需要使用 @SpringBootTest 注解來標識單元測試類,以開啟對依賴注入的支持。

以測試用戶注冊功能為例,示例代碼如下:

import?org.junit.jupiter.api.Assertions;
import?org.junit.jupiter.api.Test;
import?org.springframework.boot.test.context.SpringBootTest;

import?javax.annotation.Resource;

@SpringBootTest
public?class?UserServiceTest?{

????@Resource
????private?UserService?userService;

????@Test
????void?userRegister()?{
????????//?準備數(shù)據(jù)
????????String?userAccount?=?"yupi";
????????String?userPassword?=?"";
????????String?checkPassword?=?"123456";
????????//?執(zhí)行測試
????????long?result?=?userService.userRegister(userAccount,?userPassword,?checkPassword);
????????//?驗證結(jié)果
????????Assertions.assertEquals(-1,?result);
????????//?再準備一組數(shù)據(jù),重復測試流程
????????userAccount?=?"yu";
????????result?=?userService.userRegister(userAccount,?userPassword,?checkPassword);
????????Assertions.assertEquals(-1,?result);
????}
}

3、生成測試報告

如果系統(tǒng)的單元測試數(shù)量非常多(比如 1000 個),那么只驗證某個單元測試用例是否正確、查看單個結(jié)果是不夠的,我們需要一份全面完整的單元測試報告,便于查看單元測試覆蓋度、評估測試效果和定位問題。

測試覆蓋度 是衡量測試過程中被測試到的代碼量的一個指標,一般情況下越高越好。測試覆蓋度 100% 表示整個系統(tǒng)中所有的方法和關(guān)鍵語句都被測試到了。

下面推薦 2 種生成單元測試報告的方法。

使用 IDEA 生成單測報告

直接在 IDEA 開發(fā)工具中選擇 Run xxx with Coverage 執(zhí)行單元測試類:

然后就能看到測試覆蓋度報告了,如下圖:

顯然 Main 方法沒有被測試到,所以顯示 0%。

除了在開發(fā)工具中查看測試報告外,還可以導出報告為 HTML 文檔:

導出后,會得到一個 HTML 靜態(tài)文件目錄,打開 index.html 就能在瀏覽器中查看更詳細的單元測試報告了:

這種方式簡單靈活,不用安裝任何插件,比較推薦大家日常學習使用。

使用 jacoco 生成單測報告

JaCoCo 是一個常用的 Java 代碼覆蓋度工具,能夠自動根據(jù)單元測試執(zhí)行結(jié)果生成詳細的單測報告。

它的用法也很簡單,推薦按照官方文檔中的步驟使用。

官方文檔指路:https://www.eclemma.org/jacoco/trunk/doc/maven.html

首先在 Maven 的 pom.xml 文件中引入:

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

當然,只引入 JaCoCo 插件還是不夠的,我們通常希望在執(zhí)行單元測試后生成報告,所以還要增加 executions 執(zhí)行配置,示例代碼如下:

<plugin>
????<groupId>org.jacoco</groupId>
????<artifactId>jacoco-maven-plugin</artifactId>
????<version>0.8.11</version>
????<configuration>
????????<includes>
????????????<include>com/**/*</include>
????????</includes>
????</configuration>
????<executions>
????????<execution>
????????????<id>pre-test</id>
????????????<goals>
????????????????<goal>prepare-agent</goal>
????????????</goals>
????????</execution>
????????<execution>
????????????<id>post-test</id>
????????????<phase>test</phase>
????????????<goals>
????????????????<goal>report</goal>
????????????</goals>
????????</execution>
????</executions>
</plugin>

然后執(zhí)行 Maven 的 test 命令進行單元測試:

測試結(jié)束后,就能夠在 target 目錄中,看到生成的 JaCoCo 單元測試報告網(wǎng)站了:

打開網(wǎng)站的 index.html 文件,就能看到具體的測試報告結(jié)果,非常清晰:

通常這種方式會更適用于企業(yè)中配置流水線來自動化生成測試報告的場景。

實踐

編程導航星球的用戶中心項目詳細講解了如何使用 JUnit 編寫規(guī)范的單元測試。

???? 編程導航原創(chuàng)項目教程系列:https://yuyuanweb.feishu.cn/wiki/SePYwTc9tipQiCktw7Uc7kujnCd


為什么程序員一定要寫單元測試?的評論 (共 條)

分享到微博請遵守國家法律
万山特区| 马关县| 通城县| 莱阳市| 兴仁县| 肇州县| 德惠市| 报价| 大余县| 溧阳市| 金坛市| 海门市| 绥化市| 高尔夫| 舟山市| 尼勒克县| 镇江市| 石家庄市| 交口县| 华池县| 襄城县| 垣曲县| 大新县| 准格尔旗| 大关县| 金寨县| 鹤岗市| 肥城市| 班玛县| 丰顺县| 吉林省| 平果县| 怀安县| 临沂市| 津市市| 巴楚县| 辉南县| 临邑县| 彭山县| 博乐市| 静乐县|