日照網絡公司
掃描關注網站建設微信公眾賬號

掃一掃微信二維碼

日照網站建設公司告訴你如何進行單元測試!

昊諾網絡o2017-07-31 09:09:26o網絡知識o

日照網站建設公司告訴你如何進行單元測試!


單元測試是將應用程序分解為盡可能小的函數,并創建可重復的、自動化的測試用例的過程。在同等條件下,這些測試用例應該一直產生相同的結果,它們是應用程序的靈魂,并為今后所有應用程序的代碼提供構建的基礎。如果沒有單元測試,不常使用的函數可能長達數月都不會被發現有 bug;相反,通過使用單元測試,我們可以在任何代碼合并到主干之前就驗證每個系統函數的功能,不會等到代碼實際應用到產品中時還會出現問題。

網站建設前端架構師的主要責任是確保開發者擁有盡可能效率高的開發工具。單元測試就是其中之一,它可以用于構建任何規模的應用,無論構建應用程序邏輯的主要語言屬于前端語言還是后端語言,你都有大量的工具可以應用到工作流中。無論使用的是 PHP 的 PHPUnit、Node 的 NodeUnit,還是 JavaScript 的 QUnit,你都能找到用于構建單元測試的成熟穩定的平臺。

雖然技術棧(和與之相關的測試)有可能留給軟件架構師來決定,但前端開發人員寫出的代碼可能也需要測試。因此,熟悉盡可能多的測試工具很重要。掌握所有工具,甚至達到精通的程度,那是非常難的。但如果對基本概念有著深刻的理解,將能幫助你和你的團隊編寫出更加可測試的代碼,并快速地掌握任何測試框架。

下面首先來回顧一下這些基本概念,然后再來看一些實際的代碼。

1. 單元

“一次只做一件事,并把它做好”是構建基于單元測試的應用程序的原則。我們在寫函數時經常想同時實現很多功能,結果不僅降低了效率,還增加了測試的難度,因為這樣的函數無法復用。

思考一個簡單的函數:通過客戶的地址,計算出將產品從近的分撥區域運輸給客戶的運費。

下面來分解一下這個函數。函數要做的先是通過客戶的地址找到近的分撥區域;然后使用分撥區域的地址,計算出分撥區域到客戶地址的距離;使用這個距離,計算出將貨物從點 A 運輸到點 B 的費用。因此,雖然只有一個函數,它卻做了 3 件相互獨立的事:

(1) 根據地址找到近的分撥區域

(2) 計算兩個地址之間的距離

(3) 根據距離計算運費

回顧一下“一次只做一件事,并把它做好”的理念,很明顯可以通過 3 個獨立的函數更好地實現通過地址來查詢運費的功能。當我們對功能進行拆分后,就可以得到 3 個函數:一個根據地址找到近的分撥區域,一個計算兩個地址之間的距離,還有一個根據距離計算運費。

(1)   更多重用

現在,這 3 個函數可以在整個應用中使用了,而不只是用來計算運費。如果程序的其他部分需要找到近的分撥區域或者計算兩個地址之間的距離,可以直接調用這些已經寫好的函數?,F在,在較大的函數體中,我們不用一遍又一遍地重寫功能相同的模塊了。

(2) 更好的測試

我們可以測試每個獨立且可重用的函數,而非測試應用程序所能計算的每一條運輸路線。隨著應用程序的發展,開發一個新功能所需要創建的新函數越來越少。這樣我們用較少的低復雜度的函數完成了高復雜度的功能。

2. 測試驅動的開發

大多數人在一次接觸單元測試時,可能寫過一些功能代碼以滿足業務需求(比如上文中的計算運費的例子),然后也努力地將它重構為更小的、可重用的、可測試的代碼,之后才去思考如何寫測試用例。測試驅動的開發(test-driven development,TDD)則顛倒了這一思路,它將單元測試放在前一位,之后才是編寫功能代碼。

但如果為還沒有創建的函數寫測試用例,那些函數豈不是肯定無法通過測試嗎?的確!但測試驅動的開發的目標是,通過測試用例來描述一個正確編寫的系統應如何工作,并為實現這個系統來鋪平道路。

對于上文提到的計算運費的例子,在測試驅動的開發中會為三個實現業務需求的函數分別編寫單元測試。開發者的工作就是將一開始沒有通過單元測試的函數變為能夠通過測試的函數。先實現一個可以正確地查找出近的分撥區域的位置的函數,并通過前一個單元測試。然后,繼續實現計算距離和計算運費的函數,得到三個通過與之對應的單元測試的函數。

完成上述步驟后,我們不僅實現了應用的計算運費的功能,還讓這些函數有了完全的測試覆蓋率。

3. 一個測試驅動的例子

單元測試的理念其實非常簡單。它的基本思路是調用要測試的函數,傳遞一些預先設置好的參數,并描述結果應該是什么。下面來看看如何為通過給定距離來計算運費的函數設計功能測試:
素材圖片
QUnit有多個用于測試斷言的操作符,包括用于測試布爾值的 ok() 和用于比較復雜對象的 deepEqual()。在這個例子中,我們使用 equal() 來比較 calculateShipping() 的返回值與期望值。只要 calculateShipping(24) 返回的是 4(這個例子中確實將返回 4),這個單元測試就能通過。第三個參數——24 Miles——用來在測試輸出中標記相應單元測試的結果。

上文中通過距離計算運費的單元測試(當然也包括其他函數的單元測試)就緒后,我們就掌握了一個測試集,通過運行該測試集可以確認系統能否正常工作。如果有人要改 calculateShipping() 的函數名或者運費,這個測試集就會反饋提示失敗,因此我們能夠在有問題的代碼部署到生產環境之前就修復它們。

QUnit 的功能遠遠不止上文例子中提到的。舉例來說,它可以測試同步函數,也可以測試異步函數;它還可以與單元測試中加載的 Web 頁面進行交互(其實用 JavaScript 都能實現)。因此,如果你的單元測試包括用戶點擊鼠標或按下鍵盤時的返回值,QUnit 也能夠支持。

4. 測試覆蓋率要多大才足夠

確定合適的測試覆蓋率是很難權衡的一件事情。如果你不是在進行測試驅動的開發(這種開發中,沒有代碼是不需要單元測試的),那么確定測試覆蓋率將非常重要。如果測試所有的代碼,開發進度可能停滯不前;而如果測試不夠,就有漏掉新問題的風險。

(1) 解決分歧點

如果為已有的項目設計單元測試,大部分情況下,你可能沒有時間或者預算為現有的功能編寫各個方面 覆蓋率的測試集。但這不是問題!測試覆蓋率的好處是,即使一個單一的測試也能夠為系統建設貢獻價值。因此,在決定從哪里開始寫單元測試時,可以從能夠獲得大收益的地方開始。有時候,大的收益就是為系統簡單的部分編寫單元測試。就像在處理更重要的債務之前,先還清小額信用貸款一樣,寫一些簡單但仍有價值的測試用例是為單元測試造勢的好方法。

一旦有了能提供基本覆蓋率的測試集,就可以開始尋找系統中關鍵的部分,或者過去頻繁出問題的部分,在需求列表中為它們分別創建需求,并確保盡快推動這些需求。

(2) 從測試覆蓋率開始

如果有幸作為網站建設前端架構師啟動全新的項目,你的工作就不僅僅是設置好測試框架了,還要確保開發流程本身為單元測試做好了準備。就像寫文檔和進行代碼審核一樣,寫單元測試也要花不少時間。你需要確保任何需要測試的需求都有額外的時間來編寫單元測試,并且確認所需的測試覆蓋率。

正如前面所說的,并不是所有的功能都需要同樣的測試覆蓋率。但前提是,每一個用戶故事都是以測試覆蓋率的相關任務作為開始的。只有當所有人都認為給這些任務寫測試用例沒有必要時,才考慮去掉它。這樣我們才能確信,對于任何需要測試的功能,都已經安排了足夠的時間去完成它們。

文章關鍵詞
国产亚洲精品第一综合另类