iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
1
Cloud Native

從零開始建立自動化發佈的流水線系列 第 20

20. 自動化測試 - 觀念篇

最新內容已更新至 Blog: 使用 CI 進行自動化測試

Eric: 完成持續整合與訊息通知後,又向持續發佈的目標前進了一大步。

吉米: 是啊,完成 CI server 的架設與訊息通告的設定後,就可以立刻確定提供到版控的程式是否能正常建置。

Eric: 很好,但還不夠。我們下一步就是確保建置出來的軟體,可以正確運行功能。

吉米: 我們在提供之前的測試,不就是為了確保軟體正確運行功能嗎?

Eric: 這在軟體規模小的時候還可以,但是如果你手上的軟體己經持續發展六七年以上,還有辦法修改後的程式,每個功能都正常嗎?

吉米: 確實,通常都是只測試這次修改的功能是否正常,其他功能不太會特別去測試。

Eric: 對吧!所以這個時間,就要依賴自動測試機制,來檢查原有的功能是否正確運行。

吉米: 你說的有道理,但我對自動化測試這部份沒有經驗。

Eric: 沒關係,先跟你說自動化的觀念後,以後,你有機會會用到的。


01. 自動化測試的第一步 - 單元測試

提到自動化測試,那就一定避不開單元測試。而單元測試最主要的目的,就是 被測試的物件,商業邏輯的是否正確輸出入的結果是否符合預期

我們利用單元測試來快速測試、驗證,所開發的功能,是否能達到預期的結果。對於通過測試的功能,至少可以保證它的商業邏輯,在特定的測試的條件是正確無誤的。

02. 單元測試的五大特性

而一個好的單元測試,它一定具有 快速獨立可重現性可自我驗證即時性 這五個特性。通常將這五個特性簡稱為 FIRST 。

而一個好的單元測試,它一定具有 快速獨立可重現性可自我驗證即時性 這五個特性。通常將這五個特性簡稱為 FIRST 。

  • Fast 快速

    單元測試可以在短時間取得測試結果。

  • Independent/Isolated 獨立

    單元測試時,不需依賴其他的物件或功能,才能進行測試。

  • Repeatable 可重現的

    不管在何時何地,測試的結果應該都是相同的。

  • Self-Validating 可自我驗證

    不管單元測驗通過與否,應該可以從測試工具產生的測試報告,明白的得知測試結果與失敗原因。

  • Timely 即時

    可以當下就知道測試結果。

03. 單元測試的基本功

對於沒有撰寫過單元測試的開發者,往往不知道要從那邊開始下手。或者是手上的程式歷經 N 個人的手,內容過於複雜,無法下撰寫單元測試。

事實上,單元測試的運用與觀念,非常重視 物件導向的特性SOLID 原則。所以,假若不常用或不熟悉物件導向的開發者,初期不容易切入單元測試的世界。

筆者在這部簡單提一下 物件導向的特性SOLID 原則 ,若要進一步了解,網路上也有許多參考資料,就不詳細說明。

  • 物件導向特性

    • 封裝: 將相關的功能、參數、全部包成同一個物件。
    • 繼承: 繼承父物件的子物件,具有父物件的特定功能的同時,可以增加父類別所沒有的功能。
    • 多型: 使用相同的抽象介面,操作同介面不同實作的物件。
    • 抽象: 物件間共有的特性或功能,但不一定具有實作功能。
  • SOLID 原則

    • 單一職責原則(Single responsibility principle, SRP)

      每個物件,不管是類別、函數,負責的功能,都應該只做一件事。也因為一次只做一件事,所以它的目的是非常明確的。

      相當來說,目的越明確,範圍越小的功能,其單元測試就越容易撰寫。

    • 開放封閉原則(Open-Close principle, OCP)

      當功能變改時,該藉由增加新的程式碼來擴充系統的功能。避免修改原本的程式碼來擴充系統的功能。

      修改原本正常運行的程式碼,你很難確保這次的變更,是否如預期般,不會影響到其他相關的功能。

      就筆者經驗而言,影響到是正常的,沒影響到是運氣好,但通常會對維護上,帶來額外的負擔。

    • 里氏替換原則(Liskov substitution principle, LSP)

      簡單來說,只要是繼承父類別的物件。在程式中,只要出現父類別物件的部份,都可以用子類別替換。

    • 接口隔離原則(Interface segregation principle, ISP)

      針對不同需求的用戶,開放其對應需求的介面,提供使用。可避免不相關的需求介面異動,造成被強迫一同面對異動的情況。

      簡單來說,對不同的用戶,開放不同的功能。再用通俗一點的說法,就是見人說人話、見鬼說鬼話。

    • 依賴反轉原則(Dependency inversion principle, DIP)

      類別中,不應該直接使用另一個具有實作類別,而是使用抽象的介面,去承接繼承該介面的實作類別。它的目標就是解除物件與物件間,兩者的直接相依關係。

04. 單元測試的用途

當軟體規模大到一個程度後,後面的需求變動,往往有很大的機率出現改 A 壞 B的情況。在單元測試保護的情況下,程式改壞了,測試就會直接亮紅燈,以確保程式功能的正確性。

或是軟體需要重構的情況下,確保軟體不會因為程式碼的整理,而造成功能的損壞。

再者時,軟體己具有一定規模時,快速驗證新增功能是否正常,而不需要每次都從重跑流程,造成時間與效率的浪費。

所以 單元測試,真正發揮它的 POWER 的時間點,在於軟體後續長期維護、需求變動、重構時,才能真正的明白為什麼需要單元測試。

05. 注意事項

在單元測試時,不需要過份追求程式覆蓋率測試案例

過度追求程式覆蓋率或測試案例,可能會造成無意義的測試案例、或是測試案例維護成本過高的情況。

只需針對 使用頻率最高曾經出錯的功能 即可。


Eric: 當我們寫完了自動測試,當然也會希望 CI server 在建置時,順便幫我們確認提交變更後的程式,是否可以通過測試。

吉米: 嗯嗯,所以我們接著要去 Azure DevOps、Jenkins、Travis CI 這幾個 CI Server 中,設定執行自動測試的動作吧。

Eric: 沒錯。那我們就接著進行 CI Server 的設定吧。

<<待續>>


延伸閱讀

  1. 91, 30天快速上手TD
  2. 10. 從被動變主動—依賴反轉

上一篇
19. CI 訊息通知 - Microsoft Teams
下一篇
21. 自動化測試 - 實作篇
系列文
從零開始建立自動化發佈的流水線30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言