爲什麼開發人員不願意寫單元測試?
單元測試是專業開發人員確保真正完成編程任務的有效手段之一。但是實際開發中,絕大多數開發人員卻非常牴觸寫單元測試,這又是很殘酷的現實。開發人員有100個理由不寫單元測試。我觀察了超過20個項目的實際開發過程,與項目經理交談,與開發者交談後,也很理解在項目開發過程中他們所面臨的“囧境”。也許你會反駁我:“這是不可能吧,連學習軟件工程專業的大學生都知道編碼完成之後,要寫單元測試來驗證程序是否按照預期的想法工作……”,“這是什麼水平的碼農,難道他們不知道TDD嗎……難道他們不重視測試嗎,他們不使用自動化測試嗎……”,“他們是敏捷開發嗎……沒有單元測試,怎麼適應快速迭代,構建應用,快速交付……”。沒錯,你懂得這些人都懂,甚至比還懂得多,這其中有入行三五年的開發者,也有入行超過二十年的“老老鳥”,但是現實就是,他們很少在項目中寫單元測試。這就是殘酷的現實。
總結以下,開發人員爲什麼不寫單元測試?從很多次的項目回顧會議中抽取了一些典型的“不寫單元測試的理由”,畫一張圖來說明吧。可以大概分爲:認知、項目管理、技術三方面的原因:
其實,從上面的圖中可以看出,對單元測試的認知層面的理由要多一些,這其實就是“明知故犯”。
開發者關注和重視的是新技術的應用,算法的優化,架構的“優良”等等,但是其實連最基本需要做的單元測試都不做。“單元測試只能增加我們的工作量,又沒有什麼實際的效果;後面不是還有測試團隊嗎?測試缺陷後,再修改吧~”
PM關心的是項目的進度和交付的Deadline,一大堆需要寫的文檔都還沒寫呢,再別說單元測試了。“我們玩的是敏捷開發,敏捷本來就是少文檔呀,能不寫就不寫了……” (在我的另外一篇博客中,會談到敏捷開發到底需要寫哪些文檔這個話題)
高層管理者關注的是項目是否能夠按期交付和發佈,至於單元測試那是項目經理和開發者的事情,再不行讓QA去管理。但是到底質量爲什麼會出問題,發佈後爲什麼缺陷很多,很少有人會把原因歸結到“開發者沒有寫單元測試”,或者“單元測試覆蓋率低”這樣的原因上。即使有人提出了這樣的問題,也會被大家鬨笑而對:“你是做老師的吧,理論很紮實,但是項目實踐太少……”。
哎,果真如此嗎?
爲什麼要寫單元測試
同樣,放一張圖來說明,爲什麼需要單元測試的基本理由:
寫單元測試的好處
再講這個話題之前,我與軟件經理和開發者分別交談,不同的場合中的交談。我提到了一個問題:“什麼是可測試性?”幾乎沒有人能夠準確的回答這個問題。我同樣也希望能夠讀到這篇博客的開發者考慮這個問題。
本質上說:一個功能如果是不可測試的,那麼它也不會被測試。缺陷就隱藏在其中了。
創建單元測試是爲了:
- 推動更好的設計
- 糾正代碼中的錯誤,儘早的發現缺陷
- 規範編碼和規範開發者的開發行爲(習慣)
- 支持變化
- 避免迴歸缺陷
- 運行可擴展性
- 節省測試時間
- 提供工作的穩定節奏
- ……
良好的單元測試是自動化執行的,可自我驗證的,可重複執行的,一致的和快速的。
一個單元測試用例只測試一個單一邏輯,並獨立運行。
其實,無論開發者技術經驗多麼好,項目管理多麼好,開發流程多麼好,新技術、新框架都引入並採用了,TDD、FDD、ATDD等概念層面講的多麼頭頭是道,單元測試始終都是繞不過去的一道坎。爲什麼不能在如何寫好單元測試,利用有效的單元測試工具提高單元測試的實踐和通過率、自動化率方面好好思考呢?
軟件產品的質量和測試的代價其實在一開始就註定了,在沒有良好的單元測試的情況下就已經產生了危機。
認同的點個贊,不認同的看過笑笑就飄過……
分析數據不便於提供,但是結論已經不言而喻了……
單元測試和集成測試工具
作爲一名開發者,你瞭解或者知道的單元測試工具和集成測試工具有多少呢?
工具名稱 | 資源URL | 特點 |
---|---|---|
JUnit | https://junit.org/junit5/ | JUnit 5目標是爲JVM開發人員開發一個最新的基礎測試。這包括關注Java 8和更高版本,以及支持多種不同風格的測試。 |
REST Assured | http://rest-assured.io/ | 簡約的接口測試DSL 支持xml json的結構化解析 支持xpath jsonpath gpath等多種解析方式 對spring的支持比較全面 |
Selenium | https://www.selenium.dev/ | Selenium也是一個用於Web應用程序測試的工具。Selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣。支持的瀏覽器包括IE、Mozilla Firefox、Mozilla Suite等。這個工具的主要功能包括:測試與瀏覽器的兼容性——測試你的應用程序看是否能夠很好得工作在不同瀏覽器和操作系統之上。 |
TestNG | http://maven.apache.org/surefire/maven-surefire-plugin/examples/testng.html | TestNG是Java中的一個測試框架, 類似於JUnit 和NUnit, 功能都差不多, 只是功能更加強大,使用也更方便。 |
Mockito | Mockito是GitHub上使用最廣泛的Mock框架,並與JUnit結合使用Mockito框架可以創建和配置mock對象。使用Mockito簡化了具有外部依賴的類的測試開發。 | |
Spock Framework | http://spock-framework.3207229.n2.nabble.com/ | Spock是一個爲Groovy和Java語言應用程序來測試和規範的框架。這個框架的突出點在於它美妙和高效表達規範的語言。得益於JUnit Runner,Spock能夠在大多數IDE、編譯工具、持續集成服務下工作。Spock的靈感源於JUnit,JMock, RSpec, Groovy,,Scala,,Vulcans以及其他優秀的框架形態。 |
Cucumber | https://cucumber.io/ | Cucumber是一個支持BDD(Behavior Driven Development),即行爲驅動開發的自動化測試框架。在進行單元測試或者集成測試之前,事先將測試的步驟和驗證信息用通用的語言(英語)定義好,使得測試的步驟、單元測試和集成測試每一步執行的目的能被非開發人員讀懂,並且寫單元測試和集成測試的人員可以依據事先寫好的框架進行代碼的編寫,達到行爲驅動開發的目的。 |
Spring Test |
Spring Test是Spring MVC自帶了一個非常有用的測試框架,該框架無需進行Web容器即可進行深度測試。 在Spring的框架下,做單元測試使用spring中對Junit框架的整合功能 |
|
DBUnit | http://dbunit.sourceforge.net/ | DBUnit是一個基於Junit擴展的數據庫測試框架。它提供了大量的類對與數據庫相關的操作進行了抽象和封裝,雖然在80%的情況,你只需使用它極少的api。它通過使用用戶自定義的數據集以及相關操作使數據庫處於一種可知的狀態,從而使得測試自動化、可重複和相對獨立。 |
Robot Framework | https://robotframework.org/ | Robot Framework是一個基於Python的,可擴展的關鍵字驅動的測試自動化框架,用於端到端驗收測試和驗收測試驅動開發(ATDD)。它可用於測試分佈式異構應用程序,其中驗證需要涉及多種技術和接口。 |
Httpunit | http://www.httpunit.org/ |
HttpUnit是一個開源的測試工具,是基於JUnit的一個測試框架,主要關注於測試Web應用,解決使用JUnit框架無法對遠程Web內容進行測試的弊端。HttpUnit提供的幫助類讓測試者可以通過Java類和服務器進行交互,並且將服務器端的響應當作文本或者DOM對象進行處理。
HttpUnit用Java編寫,它模擬瀏覽器行爲的相關部分,包括表單提交、JavaScript、基本http身份驗證、cookies和自動頁面重定向,並允許Java測試代碼以文本、XML DOM或表單、表和鏈接的容器的形式檢查返回的頁面。當與JUnit這樣的框架結合時,編寫能夠非常快速地驗證web站點功能的測試是相當容易的。 |
NoSQLUnit | https://www.oschina.net/p/nosqlunit |
NoSQL的單元測試工具 授權協議:Apache 開發語言:Java 操作系統:跨平臺 NoSQLUnit 是一個 JUnit 的擴展,用來爲那些使用了 NoSQL 後端的應用提供單元測試和集成測試的工具。 |
JsTestDriver | https://www.oschina.net/p/jstestdriver |
JavaScript單元測試工具 授權協議:Apache 開發語言:JavaScript 操作系統:跨平臺 JsTestDriver是一個JavaScript單元測試工具,易於與持續構建系統相集成並能夠在多個瀏覽器上運行測試輕鬆實現TDD風格的開發。當在項目中配置好js-test-driver以後,如同junit測試java文件一般,js-test-driver可以直接通過直接運行js文件,來對js文件單元測試。 |
Venus |
JavaScript 單元測試工具 授權協議:Apache 2.0 開發語言:JavaScript 操作系統:跨平臺 開發廠商:Linkedin Venus 是一個 JavaScript (JS)的測試工具,可以簡化運行單元測試。當你在 JS 開發一個基於瀏覽器的項目時,你想創建單元測試並頻繁地運行它們。通常,你會用一些庫比如 Mocha 或 Jasmine,寫一個單元測試,這些庫可以讓你定義測試用例,並提供 API 來編寫判斷。 通過創建一個工具,可以讓你更輕鬆地與現有的庫一起工作。一下是 Venus 的主要好處: 在你的測試使用 Simple annotations, 來指定你要使用的測試庫,你要測試的文件,其它文件依賴,以及測試工具模板 |
|
Fluint |
Flex 單元測試工具 授權協議:MIT 開發語言:ActionScript 操作系統:跨平臺 Fluint是一個 Flex 單元測試工具,對於Flex單元和集成測試,“Fluint”非常簡潔。它是爲編寫Flex2或Flex3應用的開發者提供的測試框架,無論這些應用是通過Adobe Flash Player在瀏覽器中部署的,還是通過Adobe AIR在桌面上部署的。 Fluint最初是作爲Digital Primates的內部工具開發的,用以測試一些非常大的項目。隨着Flex社區對其需求的不斷增長,Digital Primates決定把其發佈爲一個開源項目。儘管針對Flex有其他的單元測試解決方案,按照Labriala的說法,Fluint仍填補了重要空白。 |
|
Buster.JS | https://www.oschina.net/p/buster-js/related |
JavaScript 單元測試工具 Buster.JS 授權協議:BSD 開發語言:JavaScript 查看源碼» 操作系統:跨平臺 Buster.JS 是 JavaScript 的單元測試工具包,** **瀏覽器測試工具包;**Buster.js 可以自動的在瀏覽器上測試,像 JsTestDriver ;QUnit 風格 靜態 HTML 頁面測試 ; 在一些不知名的瀏覽器上測試,像 PhantomJS 和 jsdom ; Node.js 測試工具包; 靈活; Buster.js 裏面幾乎含有所有的公共 API 。你可自己書寫* 測試報告* 來自定義 buster 的輸出(buster 裏面已經有 xUnit XML, traditional dots, specification, tap, TeamCity ),也可以編寫擴展其他測試框架(buster 裏面已經有 buster-jstestdriver ),添加你自己的測試語法(xUnit 和 BDD); 更多相關信息請看 the overview 。 |
SQLUnit | https://sourceforge.net/projects/sqlunit/ |
存儲過程單元測試工具 SQLUnit 授權協議:未知 開發語言:Java 操作系統:跨平臺 SQLUnit是一個用於對存儲過程進行單元測試的工具,其實也可以用於做針對數據庫數據、性能的測試等,延續了xUnit家族的一貫特性和風格,只不過它的測試是以xml的方式來編寫,但原則仍然和xUnit家族其他產品一樣,強調的是輸出和預期的比較,SQLUnit的文檔比較的少。 |
Jest |
Jest,是由Facebook開發的單元測試框架,也是Vue推薦的測試運行器之一。Vue對它的評價是: Jest 是功能最全的測試運行器。它所需的配置是最少的,默認安裝了 JSDOM,內置斷言且命令行的用戶體驗非常好。不過你需要一個能夠將單文件組件導入到測試中的預處理器。我們已經創建了 vue-jest 預處理器來處理最常見的單文件組件特性,但仍不是 vue-loader 100% 的功能。 Vue-test-utils在Vue和Jest之前提供了一個橋樑,暴露出一些接口,讓我們更加方便的通過Jest爲Vue應用編寫單元測試。 |
|
Vue-test-utils | Vue-test-utils是Vue的官方的單元測試框架,它提供了一系列非常方便的工具,使我們更加輕鬆的爲Vue構建的應用來編寫單元測試。主流的 JavaScript 測試運行器有很多,但 Vue Test Utils 都能夠支持。它是測試運行器無關的。 |