为什么我们要写单元测试用例?
生活随笔
收集整理的這篇文章主要介紹了
为什么我们要写单元测试用例?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
一些程序員會對單元測試用例存在誤區,例如:
~這東西沒啥用,就是走個形式主義。
~認為測試用例不應該是開發人員來寫,測試不應該是測試工程師的事情嗎?
我們是開發程序的,為什么要管測試的事情?搶他們飯碗這樣真的好嗎?
~每次都要先寫完代碼,集成測試都通過之后,然后再補單元測試用例,
為的是可笑的leader要求的測試覆蓋率達標。
~為什么我還要寫一遍單元測試用例?就直接拿UI或集成好的功能手動測試唄。
或者直接手動在main()里寫代碼進行測試唄,用眼睛看一下對不對不就好了嗎?
在main()中測試一下沒有問題就OK了,為什么還非得寫到junit類中?明明是畫蛇添足嘛。
~一個方法只需要一個正確的測試用例即可。。。
~認為我的代碼絕對不會有問題,那么簡單的功能,肯定不會出錯的,我有自信,不用寫測試用例。
~寫測試用例好麻煩,要準備前置步驟,準備數據,增加工作量,有時還要加班。
我想大多數程序員初期都會有上述的想法,包括當年的我在內。
下面我們就來分析一下,到底什么是單元測試,為什么要寫單元測試,單元測試的優劣,走著。
什么是單元測試? 首先,測試的目的是為了保證程序的運行是正確的,是符合業務邏輯的,是可以被正常使用的。 一般情況下,產品經理&需求提供方會召開需求會議,告訴team大家要做什么,目標是什么。 之后,測試team要拿著這些需求去分解成測試用例,而開發team要將需求分解成任務,以便開發。 兩者同時進行,在遇到歧義點時,主動發起溝通,確保測試team與開發team不存在太大的歧義點。 再科普一下測試用例,從宏觀角度來講,測試用例分為兩大類: 由測試工程師編寫的測試用例,由開發工程師編寫的測試用例。 測試工程師可能要先編寫一些場景或用例用于測試, 寫在word文檔中或錄入到類似于禪道這樣的項目管理軟件中,并且還要進行測試用例評審, 以保證正確的需求理解以及可以覆蓋到相關的業務場景。 此外,測試工程師還需要通過一些測試軟件例如jmeter、loadrunner或其他UI自動化工具 來編寫能運行的測試用例,來進行自動化測試。 什么?你說你要手動測試?那每次發版&上線前真的是要累趴下一批又一批測試工程師了。 所謂的以手動化為恥,以自動化為榮。 開發工程師這邊寫的測試用例,也可以稱為單元測試用例,引入了今天的主題, 什么是開發工程師的單元測試? 單元測試需要由開發人員進行編寫,用來檢驗我們寫的代碼是否正確,屬于白盒測試。 單元測試通常是判斷某個類中的某個方法返回的結果是否符合預期,是否拋出異常等等。 單元測試是一種保障,保障我們的代碼與預期是一致的正確的,有保障了是不是會安全感倍增呢? 在標準的開發過程中,單元測試的代碼與實際程序的代碼具有同等的重要性。 這是一種前驅式的測試方式,因為代碼寫完之后,還沒有提交到測試環境, 此時開發人員可以通過寫測試用例的方式進行自測, 以免發布到測試環境之后,被別人測出來有很嚴重的問題,讓自己很沒面子。 程序員有責任編寫功能代碼,同時也就有責任為自己的代碼編寫單元測試代碼。 執行單元測試,就是為了證明這段代碼的行為和我們期望的一致。 做好了單元測試可以縮短開發周期,提高代碼質量,提高項目的穩定性。 編寫單元測試代碼明明是會增加工作量,為什么還能縮短開發周期呢? 因為一旦發現程序中出現問題,就需要程序員去fix掉這些問題, 在不斷的fix與不斷的check的過程中,其實這就是延長開發周期了。 如果開發人員要花大量時間去解決項目后期發現的越來越多的令人頭疼的八阿哥(BUG), 那其實是很得不償失的,誰也不能保證誰的代碼一定沒有問題,包括我在內。 所謂測試不是用來證明你是對的,而是用來證明你沒有錯。 當然了,我們也可以不寫單元測試來達到測試的目的,就是所謂的人肉測試, 我們可以通過自己在main()中寫一些代碼來調用待測試方法,自己手動去執行每個main(), 用眼睛去看結果是否出現問題,也可以把服務全部跑起來,然后通過ui的方式, 用手去點擊相關功能,并用眼睛去看是否出現問題。 在人肉測試的方法中,我們的眼睛和手占了很大的比重,如果測試點很少,那這么玩絕對沒有問題, 但請試想一下,經過日積月累后,現在項目中有1000個測試點, 每次發版&上線前都需要去確認這些測試點是準確無誤的,那你的眼睛和手還夠用嗎? 就算夠用,時間一長,你也不屑于每次都要做這種簡單無趣的勞動。
一些現實中的例子 在現實中遇到了痛點,才會真正的去思考,事情都是分兩方面的,壞的一面是讓我們走彎路,碰壁。 好的一面是總結后會讓我們有所思考,有所成長。 例子1(測試前置步驟多,浪費時間) java代碼寫好后,在提交給測試工程師前需要自己先測試一下,看看是不是有什么bug, 千萬不要被測試工程師發現什么很low的問題,這樣自己太沒有面子了。。。 我們先看沒有單元測試用例的情況下,你需要編譯、打包、啟動項目(假設你是個javaweb項目), 然后在瀏覽器輸入localhost:8080/xxx/xxx 一頓折騰后終于能進入相關的頁面,哎呀,忘了還需要登錄一下,帳號密碼沒有? 沒關系,我們可以注冊嘛。一頓折騰后終于能登錄了,哎呀, 忘了要測我這個功能的用戶必須要進后臺管理平臺去配置相關的權限, 但是后臺管理平臺的服務還木有啟動,沒關系,我們可以再啟動嘛。 一頓折騰后權限配好了,哎呀,忘了還要求當前的帳號需要走一長串工作流的審批, 才會分配相應的資源,沒關系,我們可以手動去點擊然后走這個工作流嘛。 (。。。省略各種折騰。。。。 ) yes,把這些測試的前置步驟都完成了,下面終于激動的要開始在頁面上測試自己的功能了, 興奮的點擊了一下,后臺拋了一個異常出來,貌似這是一個bug。。。 沒關系,加斷點調試,定位問題,哎呀,真的是一個bug,好吧,改代碼吧,改好之后。。。 注意了,改好之后怎么辦? 您又要編譯、打包、啟動項目、打開瀏覽器輸入url、登錄、去查看那個剛才的那個功能。。。 很激動,這次妥妥的,肯定沒問題了,然后一點擊: 哎呀,又出異常了。。。查了半天,突然發現是改錯了,然后又改好了,這次妥妥的,準沒問題了。 您又要編譯、打包、啟動項目、打開瀏覽器輸入url、登錄、去查看那個剛才的那個功能。。。 看到痛點了嗎? 我們為了測試自己寫的一個功能,要做多少前置步驟?而一旦發現代碼有bug, 改好之后又要重復若干的前置步驟,浪費了大量的時間與精力, 為什么有經驗的程序員效率高,代碼質量高,工資高,這其實是工作方法的問題。 我們是否可以通過寫單元測試用例的方式,把問題暴露在沒有這一堆前置步驟的時候呢? 這樣會節省我們大量的前置步驟時間。 例子2(項目上線自動化回歸測試) 現在項目里有100個功能,這回我們新做了一個功能,新功能測試通過了,然后歡歡喜喜的去上線, 發現新功能改了一個通用方法,導致老功能出現了一個嚴重的bug,倘若這個老功能是核心功能, 那這就是嚴重的線上事故,如果沒有單元測試用例做保障,那這種線上事故將成為可能。 怎么防范這種事故的出現?每次發布前都要手動測試一遍核心的功能?這樣會不會累死了? 我們需要自動化來完成這件事情,結合jenkins+maven+junit。 例子3(修復完bug后,補上測試用例,以防后患) 生產環境出現bug的時候,救火隊員火急火燎的去分析問題,解決問題,最終發布之后呢? 除了解決問題之外,還要思考是否能通過增加某些測試用例的情況來杜絕此類問題再次發生, 自己橫向思考一下。亡羊補牢為時不晚,如果沒有最后這一步的思考, 那下次是不是此類問題還會出現呢? 分析 如果大家分析一下我們bug原因的構成, 一部分bug的原因是在編碼時沒考慮到某些case或者邊際條件。 造成這種問題的原因很多,其中很重要的一個原因是我們對工作代碼所要完成的功能思考不足, 而編寫單元測試,特別是先寫單元測試再寫工作代碼, 就可以幫助開發人員思考編寫的代碼到底要實現哪些功能,類似于測試驅動開發的感覺。 編寫單元測試代碼的過程就是促使開發人員思考代碼實現的過程, 之后實現代碼的時候,開發人員思路會更清晰,實現代碼的質量也會有相應的提升。 發現問題早發現早治療,可以避免很多低級錯誤。
TDD測試驅動開發 “大軍未動,糧草先行”,喜歡三國演義的朋友都比較熟悉。 “代碼未動,測試先行”,喜歡極限編程的朋友都比較熟悉。 在沒有開始編寫自己的業務代碼之前,先把測試用例寫好,再補全業務代碼, 使用用測試用例來驅動開發業務代碼。 我們在設計測試用例的時候,其實也是在設計我們業務代碼的過程, 我們要去預先思考,我們的業務代碼要處理哪些問題,哪些邊界條件,哪些流程等等。 這個過程會使得我們的流程更加有保障,會讓我們的業務代碼更具有條理性,安全性。 在業務代碼沒有編寫的情況下,就編寫測試用例,怎么寫啊?寫完不是都會報錯嗎? 沒錯,報錯就對了,因為我們的業務代碼還沒有編寫,此時再去補全業務代碼即可, 先補全到不報錯就可以了。 TDD步驟 1.思考一下這個測試用例該如何編寫,我們的業務類需要提供哪些功能,方法提供哪些功能? 其實這是一個設計的過程,讓我們可以站在使用者的角度去思考和觀察問題, 驅動我們把代碼設計成可測試的&松耦合的,設計完成之后先編寫測試用例。 編寫好測試用例之后,會報很多紅叉子(編譯錯誤),這是正常的, 因為我們的被測試類與方法此時還沒有建立。 此時再去編寫測試用例要測試的業務類與方法(測試用例寫在被測試類與方法的前面), 之后再去run這些用例,肯定是失敗的,因為被測試的方法里還什么都沒有。 第一步就完成了,截止到讓測試用例執行的時候都是失敗就可以了。 2.編寫代碼讓測試用例執行成功&通過,只要通過測試用例即可,不用考慮其他。 3.重構代碼,繼續讓測試用例繼續保持通過,此時可以大膽的重構, 因為已經有若干個測試用例做保障,如果重構出了問題也不用擔心,因為測試用例會報錯, 開發者可以在第一時間知道錯誤。 總結:使用TDD,使我們換位思考,轉換到使用者的角度去設計程序,開發程序, 使程序天然是可測試性的,提升了安全性。 PS:對極限編程感興趣的童鞋可以延伸搜一下結對編程。
單元測試的優勢 減少人肉測試,為自動化測試打基礎 快速保障業務代碼的正確性,減少人肉測試,減少人工投入成本,整體上增加工作效率。 加上各種測試工具配合使用,可以形成可視化的測試報告以及測試覆蓋率文檔,讓測試指標可量化。 讓代碼維護更容易 所謂維護性,就是別人看到你寫的代碼,能不能很快的看懂并修改你的代碼。 如果你寫的代碼像一坨。。。那么無形中會給其他同事修改你的代碼造成了巨大的壓力與屏障。 由于給代碼寫很多單元測試,相當于給代碼加上了規格說明書, 開發人員通過讀單元測試代碼也能夠幫助開發人員理解現有代碼, 能夠向其他程序員展現你的程序該如何調用。 很多開源項目都有相當量的單元測試代碼,通過讀這些測試代碼會有助于理解生產源代碼。 提升反饋速度,減少重復工作,提高開發效率 開發人員實現某個功能或者修補了某個bug,如果有相應的單元測試支持的話, 開發人員可以馬上通過運行單元測試來驗證之前完成的代碼是否正確, 而不需要反復通過發布war包、啟動容器、通過瀏覽器輸入數據等繁瑣的步驟來驗證所完成的功能。 不會浪費時間,而相反是節省時間。 放心大膽的去修改老代碼、去重構、去改進質量 保證你最后的代碼修改不會破壞之前代碼的功能。項目越做越大,代碼越來越多, 特別涉及到一些公用接口之類的代碼或是底層的基礎庫, 誰也不敢保證這次修改的代碼不會破壞之前的功能, 所以與此相關的需求會被擱置或推遲,由于不敢改進代碼,代碼也變得越來越難以維護, 質量也越來越差,因為害怕牽一發而動全身,導致代碼越來越爛。 由于代碼的歷史功能都有相應的單元測試保證,相當于有了一層防護網,修改了某些代碼以后, 通過運行相關的單元測試就可以驗證出新調整的功能是否有影響到之前的功能。 當然要實現到這種程度需要很大的付出,不但要能夠達到比較高的測試覆蓋率, 而且單元測試代碼的編寫質量也要有保證。 允許只驗證部分功能 當一個業務邏輯包含了若干個service方法時, 我只想單獨跑其中的一個service方法的測試用例成為可能。 消除外部依賴,只關注單獨的一個service方法。
單元測試的劣勢 學習成本 如果只是單純的使用Junit或是TestNG這樣的基礎單元測試框架往往無法應對復雜的單元測試情況, 所以勢必要借助很多第三方的框架和技術(easymock,jmock,jenkins,maven&gradle等等), 這些框架和技術的學習還是會增加學習的成本和難度。 但其實學習這些知識點也是一個程序員成長的過程,所以說還好。 增加工作量 單元測試跟生產代碼是一樣的,并不會因為是用來測試的就有所不同, 開發人員同樣要面對測試代碼的編寫、維護等工作,也同樣要面對避免重復代碼等一系列問題, 能否寫出好的測試代碼還是取決于開發人員的設計和編碼能力。 寫測試代碼是需要花時間和精力的,因此會增加一部分工作量。 推廣和運用單元測試需要比較大的投入 只有在每個開發人員都編寫了足夠的、質量好的單元測試代碼, 大家才能真正享受到單元測試帶給我們的好處。 在達到這種層度以前,還需要不少時間和資源的投入。
Junit4測試框架 上面的話術都是理論派,那我們下面就需要實際的來寫一些單元測試的代碼了,用什么寫呢? 首選是用Junit,Junit是一個測試框架,類似的框架還有類似于TestNG等等, Junit可以用來編寫單元測試用例,并可以自動化的去運行測試用例,以減少之前人肉測試的痛點, 使用Junit能夠幫助我們減少在開發過程中的錯誤,把Bug扼殺在萌芽之中, 有利于代碼的后期維護和檢查。 使用jenkins+maven+junit,讓成建制的自動化執行測試用例變成可能。 使用eclipse等IDE或者使用maven插件生成測試報告,可以直觀的看到測試結果, 一般使用紅色表示執行失敗,用綠色表示執行成功。 Junit4常見注解
Assert斷言
如果沒有斷言,我們一般會在測試方法中使用System.out.println()來將返回值打印到控制臺,
然后用眼睛去看,這還是所謂的人肉測試,那如果有成百個測試方法,那眼睛豈不是要累死了。
除了在測試方法中使用輸出語句之外,我們還可以使用斷言,來判斷程序是否符合某個條件,
讓Junit自動去執行去比較期待值與實際值(被測試方法的返回值)是否一致,
而不用肉眼觀察的方式來完成。
斷言為自動化測試打下了一個良好的基礎。如果實際值與期待值一致,則測試通過,
否則測試失敗。如果有可視化界面的話會發現測試通過為綠色狀態,測試失敗為紅色狀態。
斷言在org.junit.Assert類中,有一組以assert開頭的方法用于斷言測試,基本上涵蓋了大部分需求。
下面列舉幾個常用的,如果有需要的話可以直接調用assertFail方法讓斷言直接失敗。
Runner運行器
junit框架使用runner來調用并運行&執行我們的單元測試用例,junit中存在多個不同的runner,
每個runner都會有特殊的功能,我們根據需求來使用不同的runner。
如果沒有指定特定的runner,則junit會使用TestClassRunner.class作為默認runner。
我們通過@RunWith(TestClassRunner.class)來指定一個runner,需要修飾在類上。
只要對一個類指定了runner,那么這個類中的所有方法都被這個runner來調用。
在寫測試用例的過程中,我們經常需要獲取spring容器中的bean對象來測試業務邏輯,
那么我們就需要一個可以自動獲取spring容器的runner:SpringJUnit4ClassRunner。
結合spring的junit4例子
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/app-config.xml")
@Transactional // 事務自動回滾
public class AATest {@ResourceIndexService indexService;/*** Title: 注冊測試用例正確.<br>* Description: registerTest<br>* CreateDate: 2017年6月19日 下午4:36:00<br>** @category registerTest*/@Testpublic void studentRegisterTrueTest() throws Exception {final UserRegisterValidationForm paramForm = new UserRegisterValidationForm();paramForm.setPhone("1706868699");paramForm.setPwd(SHAUtil.encode("caowei123"));final CommonJsonObject<User> json = indexService.studentRegister(paramForm, null);Assert.assertTrue(json.getCode() == 200);}
? Suite打包測試 在一個正兒八經的項目中,只寫一個測試類是不可能的,我們通常會寫出很多很多個測試類。 可是這些測試類必須一個一個的執行,也是比較麻煩的事情,還是相當于半個人肉測試。 因此Junit為我們提供了打包測試的功能,將所有需要運行的測試類集中起來, 一次性的運行完畢,大大的方便了我們的測試工作。 當然我們還可以打造自己的測試樹形結構,Suite是可以嵌套的,一個父Suite中包含了多個子Suite, 子Suite中包含了若干個測試類,每個測試類中又包含了若干個測試用例方法。 Suite允許我們自己靈活的來管理測試力度,這次我想把所有的用例都跑一遍,執行父Suite就可以, 下次我想只跑某個模塊下的測試用例,執行某個子Suite就可以。 具體代碼如下: import org.junit.runner.RunWith; import org.junit.runners.Suite;@RunWith(Suite.class) @Suite.SuiteClasses({ATest.class, BTest.class}) public class AllTests {} 這里需要使用Suite.class作為Runner,在@Suite.SuiteClasses中需要寫上需要聚合的測試類。 PS:如果項目中使用到了maven,maven會自動運行所有的測試用例,可以代替suite功能。 參數化測試 我們經常會給待測試方法傳入不同的參數來檢驗被測試方法是否達到預期效果,例如邊界測試等等。 參數的不同就會導致要寫多個不同的測試用例方法,那這樣豈不是很麻煩? 我們可以使用參數化測試,只寫一個測試用例方法即可,把不同的參數一次性傳遞給被測試方法。 @RunWith(Parameterized.class) public class Junit4Test2 {private int param;private int result;public Junit4Test2(int param, int result) {this.param = param;this.result = result;}@Parameterspublic static Collection data() {return Arrays.asList(new Object[][] { { 1, 2 }, { 2, 3 }, { 4, 5 }, });}@Test()public void test1() {//使用參數化測試Assert.assertEquals(result, JunitDemo.demo(param));}@Test()public void test2() {//未使用參數化測試Assert.assertEquals(2, JunitDemo.demo(1));} } @RunWith(Parameterized.class)這條語句就是為這個類指定了一個參數化的Runner。 如果是帶Spring的測試用例就不能使用這種方式,@RunWith(SpringJUnit4ClassRunner.class)。 每個測試類只能使用一個@RunWith,因此Sutie與Parameterized的用武之地就不是那么的大了。 Junit4注意事項 ~測試用例類使用public修飾; ~測試用例的測試方法使用public修飾; ~測試用例的測試方法的返回值應該是void; ~測試用例中測試方法不應該有任何參數; ~在Eclipse中用鼠標選中一個測試方法點擊run或debug則會只執行當前的測試方法, 否則會執行測試類中所有的測試方法。
注意事項&經驗總結 ~盡可能的開發出可測試性的代碼,這樣更容易提升代碼的健壯性、安全性。 在編寫代碼的同時也要去思考,如何能讓這些代碼可以被測試,或者直接使用TDD。 ~查詢條件帶時間的,尤其是要拿當前時間的地方,需要通過參數傳進去, 不然,沒法寫測試用例(寫完測試用例還要造實時數據比較麻煩)。 ~不要把類似于HttpServletRequest、HttpServletResponse這種對象傳遞進service方法, 編寫單元測試的時候,不好模擬這種對象,并且這些對象屬于web層,不應該進入到service層。 ~不要使用System.out.print來寫測試用例,需要使用Assert類來進行判斷,否則還是人肉測試。 ~盡可能的自動化,自動化回歸測試+jenkins+maven+junit自動跑所有的單元測試用例+api測試工具, 把單元測試用例的威力彰顯出來,單元測試+持續集成+自動化才是王道。 ~測試覆蓋率,單元測試覆蓋率查看可以使用maven的插件來完成,還有測試報告,非常直觀。 ~不要把測試用例玩成形式主義。 在真正測試之前,就先要跑測試用例,看測試用例能不能通過。 ? 養成習慣:給別人調用之前,先跑一下自己的單元測試用例,看能不能跑過? ~在維護&重構代碼的同時也要去維護&重構測試用例代碼,否則可能會造成編譯錯誤或運行錯誤。 ~線上出現問題,解決完畢后,去思考是否對這個case可以用增加測試用例的方式來提升質量。 ~不要把單元測試設計的非常復雜,要保證可讀性,簡單性。 ~單元測試不能依賴時間與空間的變化而導致不同的執行結果,保證無論何時何地執行結果都一致。 例如:早上7點執行與晚上7點執行的結果不同,使用A機器與B機器執行的結果不同等等。 ~service方法的insert&update方法需要傳一個boolean或int回來,而非void。 因為個別情況會導致數據庫保存失敗但沒有報錯,程序認為執行成功的窘境。 ~需要有專門的數據庫留給跑測試用例,在構建測試環境時自動化運行單元測試用例。 ~在代碼評審&review的時候,別忘了對單元測試用例也進行一下評審&review。 ~核心重要功能,需要多個正確錯誤的用例。邊角料功能可不加測試用例。 我們在寫測試用例的時候,大多數只寫邏輯正確時的測試用例,但卻忽略了邏輯錯誤時的測試用例, 正常情況下, 錯誤的測試用例也非常重要,例如:如果輸入5,方法會拋異常, 但輸入小于5的數就正常,此時我們應該至少有一個用例要寫成5,我們要嘗試, 給程序錯誤參數的時候,程序是否會信守承諾的拋出異常,如果能拋出異常, 代表我們的程序沒有問題,是比較健壯的。相反如果沒有寫錯誤的測試用例,則健壯性降低, 會有出現bug的可能,就是輸入5也沒有拋異常,這就是bug了。
controller層方法是否要寫junit單元測試? 正方:寫,如果controller層與service層都是一個人寫的那確實有些重復,但對于跨團隊作戰, 尤其是分布式架構,分布式團隊,就需要寫,這樣質量更高。 可以使用類似于easymock等框架來模擬HttpServletRequest對象進行單元測試。 反方:不寫,controller方法的邏輯較少,一般只是數據封裝以及參數檢查,沒有必要寫, 并且controller層的測試用例與service層的測試用例會有重復的情況,浪費工作量。 個人觀點:無論寫與不寫都需要有自動化API測試工具跟著, 例如jenkins+newman、postman、jmeter等,controller層的單元測試用例的優先級沒有service層高。
總結 寫代碼是需要不斷的進行重構的,因為誰也沒有把握能一次性就寫出非常優雅毫無破綻的代碼, 更何況隨著訪問量、代碼量的激增,更加的需要通過重構來保障代碼健康、穩定的運行。 那單元測試用例,就好比是一道安全網,在你重構出錯的時候,安全網會第一時間知道, 會第一時間通知你,改錯了,這其實是一種前趨式的解決潛在bug,把bug扼殺在搖籃中。 有了安全網,就可以放心大膽地去重構我們的代碼。 綜上所述,其實單元測試的重要性很簡單, 不寫單元測試,你怎么知道你的代碼寫的對不對? 沒有足夠豐富的測試用例,你怎么知道用戶會怎么使用到你的代碼, 你又怎么會知道你的代碼應該怎么被執行呢? 所以,單元測試很重要。和寫代碼一樣重要。所謂的:無單測,不編碼! 個人建議,如果是核心&重要的功能,不僅必須要寫測試用例還必須要寫多個用例, 正確的用例,錯誤的用例都要寫,至于簡單&非核心業務,用例可以適當的省略, 并且測試用例覆蓋率也是一個可前移的量化指標,最終我們是通過測試用例這種手段, 來保證我們代碼的質量,沒有質量,再談其他都變得沒有意義了。 主要是看你的付出產出比是否值當,值就寫,不值就不寫,至于度,自己拿捏。
什么是單元測試? 首先,測試的目的是為了保證程序的運行是正確的,是符合業務邏輯的,是可以被正常使用的。 一般情況下,產品經理&需求提供方會召開需求會議,告訴team大家要做什么,目標是什么。 之后,測試team要拿著這些需求去分解成測試用例,而開發team要將需求分解成任務,以便開發。 兩者同時進行,在遇到歧義點時,主動發起溝通,確保測試team與開發team不存在太大的歧義點。 再科普一下測試用例,從宏觀角度來講,測試用例分為兩大類: 由測試工程師編寫的測試用例,由開發工程師編寫的測試用例。 測試工程師可能要先編寫一些場景或用例用于測試, 寫在word文檔中或錄入到類似于禪道這樣的項目管理軟件中,并且還要進行測試用例評審, 以保證正確的需求理解以及可以覆蓋到相關的業務場景。 此外,測試工程師還需要通過一些測試軟件例如jmeter、loadrunner或其他UI自動化工具 來編寫能運行的測試用例,來進行自動化測試。 什么?你說你要手動測試?那每次發版&上線前真的是要累趴下一批又一批測試工程師了。 所謂的以手動化為恥,以自動化為榮。 開發工程師這邊寫的測試用例,也可以稱為單元測試用例,引入了今天的主題, 什么是開發工程師的單元測試? 單元測試需要由開發人員進行編寫,用來檢驗我們寫的代碼是否正確,屬于白盒測試。 單元測試通常是判斷某個類中的某個方法返回的結果是否符合預期,是否拋出異常等等。 單元測試是一種保障,保障我們的代碼與預期是一致的正確的,有保障了是不是會安全感倍增呢? 在標準的開發過程中,單元測試的代碼與實際程序的代碼具有同等的重要性。 這是一種前驅式的測試方式,因為代碼寫完之后,還沒有提交到測試環境, 此時開發人員可以通過寫測試用例的方式進行自測, 以免發布到測試環境之后,被別人測出來有很嚴重的問題,讓自己很沒面子。 程序員有責任編寫功能代碼,同時也就有責任為自己的代碼編寫單元測試代碼。 執行單元測試,就是為了證明這段代碼的行為和我們期望的一致。 做好了單元測試可以縮短開發周期,提高代碼質量,提高項目的穩定性。 編寫單元測試代碼明明是會增加工作量,為什么還能縮短開發周期呢? 因為一旦發現程序中出現問題,就需要程序員去fix掉這些問題, 在不斷的fix與不斷的check的過程中,其實這就是延長開發周期了。 如果開發人員要花大量時間去解決項目后期發現的越來越多的令人頭疼的八阿哥(BUG), 那其實是很得不償失的,誰也不能保證誰的代碼一定沒有問題,包括我在內。 所謂測試不是用來證明你是對的,而是用來證明你沒有錯。 當然了,我們也可以不寫單元測試來達到測試的目的,就是所謂的人肉測試, 我們可以通過自己在main()中寫一些代碼來調用待測試方法,自己手動去執行每個main(), 用眼睛去看結果是否出現問題,也可以把服務全部跑起來,然后通過ui的方式, 用手去點擊相關功能,并用眼睛去看是否出現問題。 在人肉測試的方法中,我們的眼睛和手占了很大的比重,如果測試點很少,那這么玩絕對沒有問題, 但請試想一下,經過日積月累后,現在項目中有1000個測試點, 每次發版&上線前都需要去確認這些測試點是準確無誤的,那你的眼睛和手還夠用嗎? 就算夠用,時間一長,你也不屑于每次都要做這種簡單無趣的勞動。
一些現實中的例子 在現實中遇到了痛點,才會真正的去思考,事情都是分兩方面的,壞的一面是讓我們走彎路,碰壁。 好的一面是總結后會讓我們有所思考,有所成長。 例子1(測試前置步驟多,浪費時間) java代碼寫好后,在提交給測試工程師前需要自己先測試一下,看看是不是有什么bug, 千萬不要被測試工程師發現什么很low的問題,這樣自己太沒有面子了。。。 我們先看沒有單元測試用例的情況下,你需要編譯、打包、啟動項目(假設你是個javaweb項目), 然后在瀏覽器輸入localhost:8080/xxx/xxx 一頓折騰后終于能進入相關的頁面,哎呀,忘了還需要登錄一下,帳號密碼沒有? 沒關系,我們可以注冊嘛。一頓折騰后終于能登錄了,哎呀, 忘了要測我這個功能的用戶必須要進后臺管理平臺去配置相關的權限, 但是后臺管理平臺的服務還木有啟動,沒關系,我們可以再啟動嘛。 一頓折騰后權限配好了,哎呀,忘了還要求當前的帳號需要走一長串工作流的審批, 才會分配相應的資源,沒關系,我們可以手動去點擊然后走這個工作流嘛。 (。。。省略各種折騰。。。。 ) yes,把這些測試的前置步驟都完成了,下面終于激動的要開始在頁面上測試自己的功能了, 興奮的點擊了一下,后臺拋了一個異常出來,貌似這是一個bug。。。 沒關系,加斷點調試,定位問題,哎呀,真的是一個bug,好吧,改代碼吧,改好之后。。。 注意了,改好之后怎么辦? 您又要編譯、打包、啟動項目、打開瀏覽器輸入url、登錄、去查看那個剛才的那個功能。。。 很激動,這次妥妥的,肯定沒問題了,然后一點擊: 哎呀,又出異常了。。。查了半天,突然發現是改錯了,然后又改好了,這次妥妥的,準沒問題了。 您又要編譯、打包、啟動項目、打開瀏覽器輸入url、登錄、去查看那個剛才的那個功能。。。 看到痛點了嗎? 我們為了測試自己寫的一個功能,要做多少前置步驟?而一旦發現代碼有bug, 改好之后又要重復若干的前置步驟,浪費了大量的時間與精力, 為什么有經驗的程序員效率高,代碼質量高,工資高,這其實是工作方法的問題。 我們是否可以通過寫單元測試用例的方式,把問題暴露在沒有這一堆前置步驟的時候呢? 這樣會節省我們大量的前置步驟時間。 例子2(項目上線自動化回歸測試) 現在項目里有100個功能,這回我們新做了一個功能,新功能測試通過了,然后歡歡喜喜的去上線, 發現新功能改了一個通用方法,導致老功能出現了一個嚴重的bug,倘若這個老功能是核心功能, 那這就是嚴重的線上事故,如果沒有單元測試用例做保障,那這種線上事故將成為可能。 怎么防范這種事故的出現?每次發布前都要手動測試一遍核心的功能?這樣會不會累死了? 我們需要自動化來完成這件事情,結合jenkins+maven+junit。 例子3(修復完bug后,補上測試用例,以防后患) 生產環境出現bug的時候,救火隊員火急火燎的去分析問題,解決問題,最終發布之后呢? 除了解決問題之外,還要思考是否能通過增加某些測試用例的情況來杜絕此類問題再次發生, 自己橫向思考一下。亡羊補牢為時不晚,如果沒有最后這一步的思考, 那下次是不是此類問題還會出現呢? 分析 如果大家分析一下我們bug原因的構成, 一部分bug的原因是在編碼時沒考慮到某些case或者邊際條件。 造成這種問題的原因很多,其中很重要的一個原因是我們對工作代碼所要完成的功能思考不足, 而編寫單元測試,特別是先寫單元測試再寫工作代碼, 就可以幫助開發人員思考編寫的代碼到底要實現哪些功能,類似于測試驅動開發的感覺。 編寫單元測試代碼的過程就是促使開發人員思考代碼實現的過程, 之后實現代碼的時候,開發人員思路會更清晰,實現代碼的質量也會有相應的提升。 發現問題早發現早治療,可以避免很多低級錯誤。
TDD測試驅動開發 “大軍未動,糧草先行”,喜歡三國演義的朋友都比較熟悉。 “代碼未動,測試先行”,喜歡極限編程的朋友都比較熟悉。 在沒有開始編寫自己的業務代碼之前,先把測試用例寫好,再補全業務代碼, 使用用測試用例來驅動開發業務代碼。 我們在設計測試用例的時候,其實也是在設計我們業務代碼的過程, 我們要去預先思考,我們的業務代碼要處理哪些問題,哪些邊界條件,哪些流程等等。 這個過程會使得我們的流程更加有保障,會讓我們的業務代碼更具有條理性,安全性。 在業務代碼沒有編寫的情況下,就編寫測試用例,怎么寫啊?寫完不是都會報錯嗎? 沒錯,報錯就對了,因為我們的業務代碼還沒有編寫,此時再去補全業務代碼即可, 先補全到不報錯就可以了。 TDD步驟 1.思考一下這個測試用例該如何編寫,我們的業務類需要提供哪些功能,方法提供哪些功能? 其實這是一個設計的過程,讓我們可以站在使用者的角度去思考和觀察問題, 驅動我們把代碼設計成可測試的&松耦合的,設計完成之后先編寫測試用例。 編寫好測試用例之后,會報很多紅叉子(編譯錯誤),這是正常的, 因為我們的被測試類與方法此時還沒有建立。 此時再去編寫測試用例要測試的業務類與方法(測試用例寫在被測試類與方法的前面), 之后再去run這些用例,肯定是失敗的,因為被測試的方法里還什么都沒有。 第一步就完成了,截止到讓測試用例執行的時候都是失敗就可以了。 2.編寫代碼讓測試用例執行成功&通過,只要通過測試用例即可,不用考慮其他。 3.重構代碼,繼續讓測試用例繼續保持通過,此時可以大膽的重構, 因為已經有若干個測試用例做保障,如果重構出了問題也不用擔心,因為測試用例會報錯, 開發者可以在第一時間知道錯誤。 總結:使用TDD,使我們換位思考,轉換到使用者的角度去設計程序,開發程序, 使程序天然是可測試性的,提升了安全性。 PS:對極限編程感興趣的童鞋可以延伸搜一下結對編程。
單元測試的優勢 減少人肉測試,為自動化測試打基礎 快速保障業務代碼的正確性,減少人肉測試,減少人工投入成本,整體上增加工作效率。 加上各種測試工具配合使用,可以形成可視化的測試報告以及測試覆蓋率文檔,讓測試指標可量化。 讓代碼維護更容易 所謂維護性,就是別人看到你寫的代碼,能不能很快的看懂并修改你的代碼。 如果你寫的代碼像一坨。。。那么無形中會給其他同事修改你的代碼造成了巨大的壓力與屏障。 由于給代碼寫很多單元測試,相當于給代碼加上了規格說明書, 開發人員通過讀單元測試代碼也能夠幫助開發人員理解現有代碼, 能夠向其他程序員展現你的程序該如何調用。 很多開源項目都有相當量的單元測試代碼,通過讀這些測試代碼會有助于理解生產源代碼。 提升反饋速度,減少重復工作,提高開發效率 開發人員實現某個功能或者修補了某個bug,如果有相應的單元測試支持的話, 開發人員可以馬上通過運行單元測試來驗證之前完成的代碼是否正確, 而不需要反復通過發布war包、啟動容器、通過瀏覽器輸入數據等繁瑣的步驟來驗證所完成的功能。 不會浪費時間,而相反是節省時間。 放心大膽的去修改老代碼、去重構、去改進質量 保證你最后的代碼修改不會破壞之前代碼的功能。項目越做越大,代碼越來越多, 特別涉及到一些公用接口之類的代碼或是底層的基礎庫, 誰也不敢保證這次修改的代碼不會破壞之前的功能, 所以與此相關的需求會被擱置或推遲,由于不敢改進代碼,代碼也變得越來越難以維護, 質量也越來越差,因為害怕牽一發而動全身,導致代碼越來越爛。 由于代碼的歷史功能都有相應的單元測試保證,相當于有了一層防護網,修改了某些代碼以后, 通過運行相關的單元測試就可以驗證出新調整的功能是否有影響到之前的功能。 當然要實現到這種程度需要很大的付出,不但要能夠達到比較高的測試覆蓋率, 而且單元測試代碼的編寫質量也要有保證。 允許只驗證部分功能 當一個業務邏輯包含了若干個service方法時, 我只想單獨跑其中的一個service方法的測試用例成為可能。 消除外部依賴,只關注單獨的一個service方法。
單元測試的劣勢 學習成本 如果只是單純的使用Junit或是TestNG這樣的基礎單元測試框架往往無法應對復雜的單元測試情況, 所以勢必要借助很多第三方的框架和技術(easymock,jmock,jenkins,maven&gradle等等), 這些框架和技術的學習還是會增加學習的成本和難度。 但其實學習這些知識點也是一個程序員成長的過程,所以說還好。 增加工作量 單元測試跟生產代碼是一樣的,并不會因為是用來測試的就有所不同, 開發人員同樣要面對測試代碼的編寫、維護等工作,也同樣要面對避免重復代碼等一系列問題, 能否寫出好的測試代碼還是取決于開發人員的設計和編碼能力。 寫測試代碼是需要花時間和精力的,因此會增加一部分工作量。 推廣和運用單元測試需要比較大的投入 只有在每個開發人員都編寫了足夠的、質量好的單元測試代碼, 大家才能真正享受到單元測試帶給我們的好處。 在達到這種層度以前,還需要不少時間和資源的投入。
Junit4測試框架 上面的話術都是理論派,那我們下面就需要實際的來寫一些單元測試的代碼了,用什么寫呢? 首選是用Junit,Junit是一個測試框架,類似的框架還有類似于TestNG等等, Junit可以用來編寫單元測試用例,并可以自動化的去運行測試用例,以減少之前人肉測試的痛點, 使用Junit能夠幫助我們減少在開發過程中的錯誤,把Bug扼殺在萌芽之中, 有利于代碼的后期維護和檢查。 使用jenkins+maven+junit,讓成建制的自動化執行測試用例變成可能。 使用eclipse等IDE或者使用maven插件生成測試報告,可以直觀的看到測試結果, 一般使用紅色表示執行失敗,用綠色表示執行成功。 Junit4常見注解
| 注解名稱 | 注解描述 |
| @Test | 所有希望被運行的測試方法都應該使用該注解, 次注解來告訴junit框架,當前方法是需要被執行的測試用例。 |
| @Test (expected=NullPointerException.class)? | 期待拋出指定異常才會通過,注解中定義的異常可以是 父類異常,方法中拋的異常只要是其子類就可以。 如果沒有此注解還想要測試拋異常的情況就必須要 自己手動寫try-catch,這樣就麻煩了。 |
| @Test(timeout=5000) | 執行超出時間無法通過(單位毫秒), 對性能&執行時間比較苛刻的測試方法可以使用此注解。 |
| @Ignore("暫不執行,因為xxxx,skipped") | 忽略當前測試用例,需要寫在@Test上面。 有些用例沒寫完或者不想在自動化跑測試用例的時候執行, 那我們就需要ignore這些用例。 |
| @Before | 使用@Before來修飾單個非測試方法, 其他每個測試方法執行之前都要執行@Before修飾的方法。 可以用來創建一些測試數據&執行一些sql等初始化操作。? 無論用例成功or失敗都會去執行@Before修飾的方法。 |
| @After | 使用@After來修飾單個非測試方法, 其他每個測試方法執行之后都要執行@After修飾的方法。 可以用來關閉&回收&清理一些資源的操作。 無論用例成功or失敗都會去執行@After修飾的方法。 |
| @BeforeClass&@AfterClass | 使用@BeforeClass來修飾單個非測試方法, 使用@AfterClass來修飾單個非測試方法。 所有測試方法執行之前要執行@BeforeClass修飾的方法。 所有測試方法執行完畢之后要執行@AfterClass修飾的方法。 類比一下,@Before與@After會執行多次, 測試類中有多少個測試方法就會執行多少次, 而@BeforeClass與@AfterClass只會執行一次。 |
| @FixMethodOrder (MethodSorters.NAME_ASCENDING) | junit測試用例的執行默認是沒有順序的, 使用此標簽可以設定執行順序,此處為按文字順序執行, 修飾在類上。 |
| 斷言方法 | 描述 |
| Assert.assertEquals(a,b); | 判斷a與b是否相等,如果相等則表示測試成功。 如果不相等則表示測試失敗并拋出Error。 |
| Assert.assertNotEquals(a,b); | 判斷a與b是否不相等,如果不相等則表示測試成功。 如果相等則表示測試失敗并拋出Error。 |
| Assert.assertTrue(a); | 判斷a是否為true,如果為true則表示測試成功。 如果a不為true則表示測試失敗并拋出Error。 |
| Assert.assertFalse(a); | 判斷a是否為false,如果為false則表示測試成功。 如果a不為false則表示測試失敗并拋出Error。 |
| Assert.assertNull(a); | 判斷a是否為null,如果為null則表示測試成功。 如果a不為null則表示測試失敗并拋出Error。 |
| Assert.assertNotNull(a); | 判斷a是否為非null,如果為非null則表示測試成功。 如果a不為非null則表示測試失敗并拋出Error。 |
| Assert.assertFail(); | 這個標簽的使用是有技巧的, 如果測試方法中寫的代碼全部被成功執行并走到了最后, 但期待的是走到最后就算是測試失敗,測試成功則不應該走到最后, 那么就要使用到此標簽。 |
| Assert.assertArrayEquals(a,b); | 判斷數組a與數組b是否相等,如果相等則表示測試成功。 如果不相等則表示測試失敗并拋出Error。 |
? Suite打包測試 在一個正兒八經的項目中,只寫一個測試類是不可能的,我們通常會寫出很多很多個測試類。 可是這些測試類必須一個一個的執行,也是比較麻煩的事情,還是相當于半個人肉測試。 因此Junit為我們提供了打包測試的功能,將所有需要運行的測試類集中起來, 一次性的運行完畢,大大的方便了我們的測試工作。 當然我們還可以打造自己的測試樹形結構,Suite是可以嵌套的,一個父Suite中包含了多個子Suite, 子Suite中包含了若干個測試類,每個測試類中又包含了若干個測試用例方法。 Suite允許我們自己靈活的來管理測試力度,這次我想把所有的用例都跑一遍,執行父Suite就可以, 下次我想只跑某個模塊下的測試用例,執行某個子Suite就可以。 具體代碼如下: import org.junit.runner.RunWith; import org.junit.runners.Suite;@RunWith(Suite.class) @Suite.SuiteClasses({ATest.class, BTest.class}) public class AllTests {} 這里需要使用Suite.class作為Runner,在@Suite.SuiteClasses中需要寫上需要聚合的測試類。 PS:如果項目中使用到了maven,maven會自動運行所有的測試用例,可以代替suite功能。 參數化測試 我們經常會給待測試方法傳入不同的參數來檢驗被測試方法是否達到預期效果,例如邊界測試等等。 參數的不同就會導致要寫多個不同的測試用例方法,那這樣豈不是很麻煩? 我們可以使用參數化測試,只寫一個測試用例方法即可,把不同的參數一次性傳遞給被測試方法。 @RunWith(Parameterized.class) public class Junit4Test2 {private int param;private int result;public Junit4Test2(int param, int result) {this.param = param;this.result = result;}@Parameterspublic static Collection data() {return Arrays.asList(new Object[][] { { 1, 2 }, { 2, 3 }, { 4, 5 }, });}@Test()public void test1() {//使用參數化測試Assert.assertEquals(result, JunitDemo.demo(param));}@Test()public void test2() {//未使用參數化測試Assert.assertEquals(2, JunitDemo.demo(1));} } @RunWith(Parameterized.class)這條語句就是為這個類指定了一個參數化的Runner。 如果是帶Spring的測試用例就不能使用這種方式,@RunWith(SpringJUnit4ClassRunner.class)。 每個測試類只能使用一個@RunWith,因此Sutie與Parameterized的用武之地就不是那么的大了。 Junit4注意事項 ~測試用例類使用public修飾; ~測試用例的測試方法使用public修飾; ~測試用例的測試方法的返回值應該是void; ~測試用例中測試方法不應該有任何參數; ~在Eclipse中用鼠標選中一個測試方法點擊run或debug則會只執行當前的測試方法, 否則會執行測試類中所有的測試方法。
注意事項&經驗總結 ~盡可能的開發出可測試性的代碼,這樣更容易提升代碼的健壯性、安全性。 在編寫代碼的同時也要去思考,如何能讓這些代碼可以被測試,或者直接使用TDD。 ~查詢條件帶時間的,尤其是要拿當前時間的地方,需要通過參數傳進去, 不然,沒法寫測試用例(寫完測試用例還要造實時數據比較麻煩)。 ~不要把類似于HttpServletRequest、HttpServletResponse這種對象傳遞進service方法, 編寫單元測試的時候,不好模擬這種對象,并且這些對象屬于web層,不應該進入到service層。 ~不要使用System.out.print來寫測試用例,需要使用Assert類來進行判斷,否則還是人肉測試。 ~盡可能的自動化,自動化回歸測試+jenkins+maven+junit自動跑所有的單元測試用例+api測試工具, 把單元測試用例的威力彰顯出來,單元測試+持續集成+自動化才是王道。 ~測試覆蓋率,單元測試覆蓋率查看可以使用maven的插件來完成,還有測試報告,非常直觀。 ~不要把測試用例玩成形式主義。 在真正測試之前,就先要跑測試用例,看測試用例能不能通過。 ? 養成習慣:給別人調用之前,先跑一下自己的單元測試用例,看能不能跑過? ~在維護&重構代碼的同時也要去維護&重構測試用例代碼,否則可能會造成編譯錯誤或運行錯誤。 ~線上出現問題,解決完畢后,去思考是否對這個case可以用增加測試用例的方式來提升質量。 ~不要把單元測試設計的非常復雜,要保證可讀性,簡單性。 ~單元測試不能依賴時間與空間的變化而導致不同的執行結果,保證無論何時何地執行結果都一致。 例如:早上7點執行與晚上7點執行的結果不同,使用A機器與B機器執行的結果不同等等。 ~service方法的insert&update方法需要傳一個boolean或int回來,而非void。 因為個別情況會導致數據庫保存失敗但沒有報錯,程序認為執行成功的窘境。 ~需要有專門的數據庫留給跑測試用例,在構建測試環境時自動化運行單元測試用例。 ~在代碼評審&review的時候,別忘了對單元測試用例也進行一下評審&review。 ~核心重要功能,需要多個正確錯誤的用例。邊角料功能可不加測試用例。 我們在寫測試用例的時候,大多數只寫邏輯正確時的測試用例,但卻忽略了邏輯錯誤時的測試用例, 正常情況下, 錯誤的測試用例也非常重要,例如:如果輸入5,方法會拋異常, 但輸入小于5的數就正常,此時我們應該至少有一個用例要寫成5,我們要嘗試, 給程序錯誤參數的時候,程序是否會信守承諾的拋出異常,如果能拋出異常, 代表我們的程序沒有問題,是比較健壯的。相反如果沒有寫錯誤的測試用例,則健壯性降低, 會有出現bug的可能,就是輸入5也沒有拋異常,這就是bug了。
controller層方法是否要寫junit單元測試? 正方:寫,如果controller層與service層都是一個人寫的那確實有些重復,但對于跨團隊作戰, 尤其是分布式架構,分布式團隊,就需要寫,這樣質量更高。 可以使用類似于easymock等框架來模擬HttpServletRequest對象進行單元測試。 反方:不寫,controller方法的邏輯較少,一般只是數據封裝以及參數檢查,沒有必要寫, 并且controller層的測試用例與service層的測試用例會有重復的情況,浪費工作量。 個人觀點:無論寫與不寫都需要有自動化API測試工具跟著, 例如jenkins+newman、postman、jmeter等,controller層的單元測試用例的優先級沒有service層高。
總結 寫代碼是需要不斷的進行重構的,因為誰也沒有把握能一次性就寫出非常優雅毫無破綻的代碼, 更何況隨著訪問量、代碼量的激增,更加的需要通過重構來保障代碼健康、穩定的運行。 那單元測試用例,就好比是一道安全網,在你重構出錯的時候,安全網會第一時間知道, 會第一時間通知你,改錯了,這其實是一種前趨式的解決潛在bug,把bug扼殺在搖籃中。 有了安全網,就可以放心大膽地去重構我們的代碼。 綜上所述,其實單元測試的重要性很簡單, 不寫單元測試,你怎么知道你的代碼寫的對不對? 沒有足夠豐富的測試用例,你怎么知道用戶會怎么使用到你的代碼, 你又怎么會知道你的代碼應該怎么被執行呢? 所以,單元測試很重要。和寫代碼一樣重要。所謂的:無單測,不編碼! 個人建議,如果是核心&重要的功能,不僅必須要寫測試用例還必須要寫多個用例, 正確的用例,錯誤的用例都要寫,至于簡單&非核心業務,用例可以適當的省略, 并且測試用例覆蓋率也是一個可前移的量化指標,最終我們是通過測試用例這種手段, 來保證我們代碼的質量,沒有質量,再談其他都變得沒有意義了。 主要是看你的付出產出比是否值當,值就寫,不值就不寫,至于度,自己拿捏。
總結
以上是生活随笔為你收集整理的为什么我们要写单元测试用例?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为鸿蒙系统自带什么输入法,搜狗输入法华
- 下一篇: AI模型的大一统!浅析微软的BEIT3: