原創(chuàng)|使用教程|編輯:鄭恭琳|2020-06-24 13:53:31.750|閱讀 403 次
概述:單元測試是一種眾所周知的做法,但是還有很多改進(jìn)的空間!在這篇文章中,最有效的單元測試最佳實(shí)踐,包括一路最大化自動化工具的方法。我們還將討論代碼覆蓋率、模擬依賴關(guān)系和整體測試策略。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
單元測試是一種眾所周知的做法,但是還有很多改進(jìn)的空間!在這篇文章中,最有效的單元測試最佳實(shí)踐,包括一路最大化自動化工具的方法。我們還將討論代碼覆蓋率、模擬依賴關(guān)系和整體測試策略。
單元測試是測試應(yīng)用程序的單個(gè)單元或組件的一種做法,目的是驗(yàn)證每個(gè)單元或組件是否正常工作。通常,一個(gè)單元應(yīng)該只占應(yīng)用程序的一小部分——在Java中,它通常是單個(gè)類。請注意,我并不是在這里嚴(yán)格定義“單元”,而是由開發(fā)人員來決定每個(gè)測試的測試代碼范圍。
人們有時(shí)將“單元測試”與“集成測試”或“端到端測試”相對比。區(qū)別在于,通常通過進(jìn)行單元測試來驗(yàn)證單個(gè)可測試單元的行為,而集成測試則是在一起驗(yàn)證多個(gè)組件或整個(gè)應(yīng)用程序的行為。就像我說過的那樣,對“單元”的定義并沒有嚴(yán)格定義,具體取決于每個(gè)測試的范圍。
單元測試是一種行之有效的技術(shù),可確保軟件質(zhì)量,并帶來很多好處。這是(多個(gè))進(jìn)行單元測試的重要原因:
不幸的是,過于頻繁的開發(fā)人員要么根本不編寫單元測試,要么沒有編寫足夠的測試,要么不維護(hù)它們。我了解——單元測試有時(shí)編寫起來很棘手,或者維護(hù)起來很耗時(shí)。有時(shí)會有一個(gè)截止日期,感覺就像編寫測試會讓我們錯(cuò)過那個(gè)截止日期。但是沒有編寫足夠的單元測試或沒有編寫好的單元測試是一個(gè)容易陷入的陷阱。
因此,請考慮以下有關(guān)如何編寫干凈、可維護(hù)的自動化測試的最佳實(shí)踐建議,這些建議可以用最少的時(shí)間和精力為您提供單元測試的所有好處。
讓我們看一些構(gòu)建,運(yùn)行和維護(hù)單元測試以達(dá)到最佳結(jié)果的最佳實(shí)踐。
單元測試應(yīng)該值得信賴
如果代碼損壞并且只有代碼損壞,則測試必須失敗。否則,我們將無法相信測試結(jié)果在告訴我們什么。
單元測試應(yīng)可維護(hù)且可讀
當(dāng)生產(chǎn)代碼更改時(shí),通常需要更新測試,也可能需要調(diào)試。因此,不僅對于編寫它的人,而且對于其他開發(fā)人員,都必須易于閱讀和理解該測試。為了清楚和易讀,請始終組織和命名測試。
單元測試應(yīng)驗(yàn)證單個(gè)用例
好的測試只能驗(yàn)證一件事,而只能驗(yàn)證一件事,這意味著通常情況下,它們只能驗(yàn)證一個(gè)用例。遵循此最佳實(shí)踐的測試更簡單,更易理解,這對于可維護(hù)性和調(diào)試很有好處。驗(yàn)證不止一件事的測試很容易變得復(fù)雜且維護(hù)耗時(shí)。不要讓這種情況發(fā)生。
另一個(gè)最佳實(shí)踐是使用最少數(shù)量的斷言。有人建議每個(gè)測試只聲明一個(gè)(可能有點(diǎn)太嚴(yán)格了)。這個(gè)想法是集中于僅驗(yàn)證所測試用例所需的內(nèi)容。
單元測試應(yīng)隔離
測試應(yīng)該可以在任何機(jī)器上以任何順序運(yùn)行,而不會互相影響。如果可能,測試應(yīng)不依賴于環(huán)境因素或全局/外部狀態(tài)。具有這些依賴項(xiàng)的測試較難運(yùn)行,并且通常不穩(wěn)定,從而使其更難以調(diào)試和修復(fù),最終花費(fèi)的時(shí)間超過了所節(jié)省的時(shí)間(請參見上面的可信賴信息)。
幾年前,馬丁·福勒(Martin Fowler)撰寫了有關(guān)“單獨(dú)的”與“可社交的”代碼的文章,以描述應(yīng)用程序代碼中的依賴關(guān)系用法,以及如何相應(yīng)地設(shè)計(jì)測試。在他的文章中,“單獨(dú)的”代碼不依賴于其他單元(它更加獨(dú)立),而“可聯(lián)系的”代碼確實(shí)與其他組件交互。如果應(yīng)用程序代碼是單獨(dú)的,則測試很簡單...但是對于正在測試的社交代碼,您可以構(gòu)建“單獨(dú)”或“社交”測試。“社交測試”將依賴于真實(shí)的依賴關(guān)系以驗(yàn)證行為,而“單獨(dú)測試”則將受測代碼與依賴關(guān)系隔離開。您可以使用模擬來隔離被測代碼,并為“可社交”代碼構(gòu)建“單獨(dú)”測試。我們將在下面查看如何執(zhí)行此操作。
圖1:社交測試與孤立測試。資料來源:馬丁·福勒(Martin Fowler),2014年,“UnitTest”
通常,使用模擬作為依賴項(xiàng)會使我們的測試人員生活更加輕松,因?yàn)槲覀兛梢詾樯缃淮a生成“單獨(dú)的測試”。復(fù)雜代碼的社交測試可能需要大量設(shè)置,并且可能違反隔離和可重復(fù)的原則。但是,由于模擬是在測試中創(chuàng)建和配置的,因此它是獨(dú)立的,我們可以更好地控制依賴項(xiàng)的行為。另外,我們可以測試更多的代碼路徑。例如,我可以返回自定義值或從模擬中引發(fā)異常,以涵蓋邊界或錯(cuò)誤情況。
單元測試應(yīng)自動化
確保在自動化過程中運(yùn)行測試。這可以是每天、每小時(shí)或在持續(xù)集成或交付過程中。團(tuán)隊(duì)中的每個(gè)人都需要訪問并查看報(bào)告。作為一個(gè)團(tuán)隊(duì),討論您關(guān)心的指標(biāo):代碼覆蓋率、修改后的代碼覆蓋率、正在運(yùn)行的測試數(shù)量、性能等。
通過查看這些數(shù)字可以學(xué)到很多東西,這些數(shù)字的巨大變化通常表明可以立即解決回歸問題。
結(jié)合使用單元測試和集成測試
邁克爾·科恩(Michael Cohn)的書《成功實(shí)現(xiàn)敏捷:使用Scrum進(jìn)行軟件開發(fā)》使用測試金字塔模型解決了這一問題(請參見下圖中的插圖)。這是描述測試資源理想分配的常用模型。這個(gè)想法是,隨著您進(jìn)入金字塔,測試通常會更復(fù)雜、更脆弱、運(yùn)行更慢、調(diào)試更慢。較低的級別更加隔離和集成、更快、更易于構(gòu)建和調(diào)試。因此,自動化的單元測試應(yīng)占您測試的大部分。
單元測試應(yīng)驗(yàn)證所有細(xì)節(jié)、極端情況和邊界條件等。應(yīng)更謹(jǐn)慎地使用組件、集成、UI和功能測試,以驗(yàn)證API或應(yīng)用程序的整體行為。手動測試應(yīng)該在整個(gè)金字塔結(jié)構(gòu)中所占的比例最小,但對于發(fā)布驗(yàn)收和探索性測試仍然有用。該模型為組織提供了高度的自動化和測試覆蓋范圍,因此他們可以擴(kuò)大測試工作量,并將與構(gòu)建、運(yùn)行和維護(hù)測試相關(guān)的成本降至最低。
單元測試應(yīng)在有組織的測試實(shí)踐中執(zhí)行
為了在各個(gè)級別上推動測試的成功,并使單元測試過程具有可擴(kuò)展性和可持續(xù)性,您將需要一些其他實(shí)踐。首先,這意味著在編寫應(yīng)用程序代碼時(shí)編寫單元測試。一些組織在應(yīng)用程序代碼之前編寫測試(測試驅(qū)動或行為驅(qū)動的編程)。重要的是測試與應(yīng)用程序代碼緊密結(jié)合。測試和應(yīng)用程序代碼甚至應(yīng)該在代碼審查過程中一起審查。評論有助于您理解所編寫的代碼(因?yàn)樗麄兛梢钥吹筋A(yù)期的行為)并可以改善測試!
與代碼一起編寫測試不僅是針對新行為或計(jì)劃中的更改,對于修復(fù)錯(cuò)誤也至關(guān)重要。您修復(fù)的每個(gè)錯(cuò)誤均應(yīng)進(jìn)行測試,以驗(yàn)證該錯(cuò)誤是否已修復(fù)。這樣可以確保該錯(cuò)誤在將來保持不變。
對測試失敗采取零容忍策略。如果您的團(tuán)隊(duì)忽略測試結(jié)果,那為什么還要進(jìn)行測試呢?測試失敗應(yīng)該表明是真正的問題......因此,在浪費(fèi)質(zhì)量檢查人員的時(shí)間之前或更早就解決這些問題,或更糟糕的是,它們會進(jìn)入發(fā)布的產(chǎn)品。
解決故障所需的時(shí)間越長,這些故障最終將花費(fèi)您的組織更多的時(shí)間和金錢。因此,在重構(gòu)期間運(yùn)行測試,請?jiān)谔峤淮a之前立即運(yùn)行測試,并且在測試通過之前也不要將任務(wù)視為“完成”。
最后,維護(hù)那些測試。正如我之前說過的,如果您在應(yīng)用程序更改時(shí)沒有使這些測試保持最新狀態(tài),則它們會失去價(jià)值。尤其是如果它們失敗了,則失敗的測試會浪費(fèi)時(shí)間和金錢進(jìn)行每次失敗的調(diào)查。當(dāng)代碼更改時(shí),根據(jù)需要重構(gòu)測試。
如您所見,要使單元測試中的金錢和時(shí)間回報(bào)最大化,就需要在應(yīng)用最佳實(shí)踐方面進(jìn)行一些投資。但最終,這些回報(bào)值得進(jìn)行初始投資。
通常,代碼覆蓋率是對自動化測試運(yùn)行期間執(zhí)行了多少生產(chǎn)代碼的度量。通過運(yùn)行一組測試并查看代碼覆蓋率數(shù)據(jù),您可以大致了解正在測試的應(yīng)用程序數(shù)量。
代碼覆蓋范圍很多,最常見的是行覆蓋范圍和分支覆蓋范圍。大多數(shù)工具專注于行覆蓋率,它僅告訴您是否覆蓋特定行。分支更加精細(xì),因?yàn)樗嬖V您是否覆蓋了代碼的每個(gè)路徑。
代碼覆蓋率是一項(xiàng)重要指標(biāo),但是請記住,增加覆蓋率是達(dá)到目的的一種手段。這對于發(fā)現(xiàn)測試中的差距非常有用,但這并不是唯一要關(guān)注的事情。注意不要花費(fèi)太多的精力來嘗試達(dá)到100%的覆蓋率——這甚至可能是不可能或不可行的,實(shí)際上,測試的質(zhì)量是很重要的。話雖如此,為您的項(xiàng)目至少達(dá)到60%的覆蓋率是一個(gè)不錯(cuò)的起點(diǎn),而設(shè)定80%或更高的覆蓋率是一個(gè)好的目標(biāo)。顯然,由您決定目標(biāo)是什么。
如果您擁有自動化的工具,這不僅很有價(jià)值,它不僅可以測量代碼覆蓋率,還可以跟蹤測試覆蓋了多少修改后的代碼,因?yàn)檫@可以使您了解是否編寫了足夠的測試以及生產(chǎn)代碼的更改。
在此處查看來自Parasoft的報(bào)告和分析中心的示例代碼覆蓋率報(bào)告,如果您正在使用Parasoft Jtest進(jìn)行單元測試,則可以瀏覽該示例:
要記住的另一件事是,在編寫新測試時(shí),請注意不要只關(guān)注行覆蓋范圍,因?yàn)閱涡写a可能會導(dǎo)致多個(gè)代碼路徑,因此請確保您的測試驗(yàn)證這些代碼路徑。線覆蓋率是一個(gè)有用的快速指示器,但這并不是唯一要尋找的東西。
增加覆蓋率的最明顯方法就是簡單地為更多的代碼路徑添加更多的測試,以及被測方法的更多用例。增加覆蓋范圍的有效方法是使用參數(shù)化測試。對于Junit4,有內(nèi)置的Junit4參數(shù)化功能和諸如JunitParams之類的第三方庫。Junit5具有內(nèi)置的參數(shù)化功能。
最后,如果您尚未跟蹤測試范圍,強(qiáng)烈建議您開始。有很多工具可以提供幫助,例如Parasoft Jtest。首先測量您當(dāng)前的覆蓋范圍數(shù)字,然后為應(yīng)該覆蓋的范圍設(shè)定目標(biāo),首先解決重要的差距,然后再從那里開始工作。
盡管單元測試是確保軟件質(zhì)量的可靠技術(shù),但仍被認(rèn)為是開發(fā)人員的負(fù)擔(dān),許多團(tuán)隊(duì)仍在為此而苦苦掙扎。為了充分利用測試和自動化測試工具,測試必須是可信賴的、可維護(hù)的、可讀的、自包含的,并且必須用于驗(yàn)證單個(gè)用例。自動化是使單元測試可行和可擴(kuò)展的關(guān)鍵。
此外,軟件團(tuán)隊(duì)需要練習(xí)良好的測試技術(shù),例如與應(yīng)用程序代碼一起編寫和審查測試,維護(hù)測試以及確保立即跟蹤和糾正失敗的測試。采用這些單元測試最佳實(shí)踐可以快速改善您的單元測試結(jié)果。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn