iT邦幫忙

2021 iThome 鐵人賽

DAY 29
1
Modern Web

Javascript 從寫對到寫好系列 第 29

Day 29 - 淺談測試 - 令人安心的保護網

前言

前兩天我們討論了 Clean CodeThe Clean Coder,這兩本書都要提到一件很重要的事情,但前兩天沒有討論到,就是關於「測試」。

所以我們今天會花一點時間聊聊測試的種類、流程,當然還有最重要的 - 「為什麼要做測試?」

但如你所見,今天已經是 29 天了,我的餘日不多了(笑),所以我們會將焦點放在概念與原因,如果想要偏向實作方面的需求,歡迎到我隊友的系列文 - React 前端工程師的兩把刷子,有足足 30 天陪你度過歡樂測試生活!

測試是什麼?

要了解測試是什麼,可以先來看看軟體開發生命週期(Software Development Lifecycles),簡稱 SDLC:

image alt

其實不一定是五塊,有的會把兩塊合在一起,或者多一個 maintenance,你可以 google SDLC 看很多不同版本

雖然圖上沒有標示順序,但是起點通常都是 Planning,所以循環的順序會是這樣:

  1. Planning
  2. Analysis
  3. Design
  4. Implementation
  5. Testing & integration
  6. Planning
  7. ...

從這張圖你可以得知幾件事:

  • 前一個要先完成,下一個才可以開始做(瀑布式開發)
  • 這五件事是一個循環這樣你才會一直有工作
  • 一個專業的軟體開發團隊,需要人員至少就要五種(但人不一定有五個,可能更少)

透過這張圖,你也能更能夠理解公司或專案內其它同事,只要屬於產品開發的,分別都在做什麼事。

  • 需要有人規劃產品,市場上的定位是什麼,未來要走到什麼方向
  • 需要有人分析需求,設計業務及系統流程,通常會是專案內的 BA(Business Analytics) 或 SA(System Analytics)負責
  • 需要有人設計畫面與流程,通常會是專案內的 UI/UX
  • 需要有人寫 code,嘿對就是你
  • 需要有人測試整合交付,其實這兩個職責比較遠一點,通常是專案內的 QA(Quality Assurance)與 SRE(Site Reliability Engineering)

扯遠了,今天的主題是測試,它是介於「程式開發之後」與「程式交付之前」的一個步驟。

測試要找出什麼?

在這個步驟,最重要的就是要把,程式中會出現 bug 的,或者不符合規格需求的東西抓出來

所以,今天如果是一個老師,要盡最大善意讓他的學生成績可以合格,所以寫了一個程式,幫所有同學的分數開根號乘以 10 ((佛

如果有學生缺考沒分數,程式會算出錯誤的答案:

程式沒有 crash,但同學你的新成績是 NaN

const students = [
    { name: 'Jack', grade: 25 },
    { name: 'Allen', grade: 49 },
    { name: 'Alice' },
    { name: 'Susan', grade: 81 }
];

const newStudents = students.map(student => {
    const newGrade = Math.sqrt(student.grade) * 10;
    return { ...student, grade: newGrade };
});

console.log(newStudents);

執行結果

[
    { name: "Jack", grade: 50 },
    { name: "Allen", grade: 70 },
    { name: "Alice", grade: NaN },
    { name: "Susan", grade: 90 }
]

下面這段 code 不會有程式方面的 bug,但是沒有照著規格寫:

佛心到直接幫你調成 60 分!太佛了全部的學生都哭了

const students = [
    { name: 'Jack', grade: 25 },
    { name: 'Allen', grade: 49 },
    { name: 'Alice' },
    { name: 'Susan', grade: 81 }
];

const newStudents = students.map(student => {
    const newGrade = 60;
    return { ...student, grade: newGrade };
});

console.log(newStudents);

執行結果

[
    { name: "Jack", grade: 60 },
    { name: "Allen", grade: 60 },
    { name: "Alice", grade: 60 },
    { name: "Susan", grade: 60 }
]

也就是說,測試的重點在這兩項:

  • Verification - build the product right,是否符合效能、安全性、架構、設計風格等
  • Validation - build the right product,是否符合使用者需求

測試的範圍

根據測試的範圍來區分的話,最主要分成三塊,可以用這張「測試金字塔」來表示:

testing pyramid

由下而上分別是:

  • Unit Test
    測試單一模組、可獨立運作的最小單位,通常是 function,因為範圍小,因此專注在 input 產出 output 的過程中,由 developer 開發後自行寫 unit test,數量最多。
  • Integration Test
    構成一個模組component 的幾個 function 一起測試,可能會有前後相依性(比如先取得資料庫的資料,然後呈現在畫面上)。
    這時會根據著重點在「過程」還是「結果」而比較有差別:
    • 過程:專注在 input 產出 output 的過程中,console、DB、API 的狀況,通常由 developer 執行
    • 結果:只關注在 input 是否產出正確的 output,通常由 QA 執行
  • E2E Test
    QA 的重點戲,使用與 end-user 近似的手機版本、螢幕尺寸、Wifi 等執行環境下測試,基本上就是模擬真實的使用情境了,可以手動點點點測試,也可以寫自動化測試的程式。

從上面的範圍可以看到,測試其實沒有一個非常清楚的分野,有的是 developer 負責,有的是 QA 負責,甚至也要看公司/專案內人力的調配,也有可能 developer 會包辦 QA 的工作。

Developer 如何看待測試

對於寫 code 的人來說,最不希望聽到的,就是 QA 走向你的聲音...

但我們自己都知道,在時間有限的情況下,開發出來的程式一定都會有 bug(不然 QA 就失業了),所以才要寫測試,目的就是要確保程式「穩定」。

蛤?穩定?測試不就是要抓錯誤嗎?

是的,正是因為測試可以「很穩定地把某個情境的錯誤抓出來」,所以當我們想要修改程式,提升效能或重構架構時,在不影響商業邏輯的前提下,我們可以透過測試,保障那些已經寫好測試的情境,都能夠正常運作(因為如果不正常就會立刻被抓出來)。

聽起來很讚啊!那為什麼不是大家都在寫測試?

寫測試雖然看起來像是寫 code 之後的事情,但事實上,testing code 應該被視為產品的一部分

因為當產品本身的商業邏輯,因為客戶要求被改動了,測試的部分也要同步跟上,不然測試舊的 case 就沒意義了。

如果把一個功能寫完要 10 天,那加上測試大約會需要 1.5 ~ 2 倍的時間,也就是這個「產品」需要 15 ~ 20 天才算是完成。

如果站在 PM 的角度,心裡肯定是五味雜陳,因為你很清楚測試是重要的,但居然要花這麼多時間!很容易就會因為時程壓力,選擇放棄測試,或者沒有太多時間測試。

因此這部分也是 trade-off,做為 developer 的角色能做的,除了提升對於測試框架的熟練度,不然就是先針對重點、複雜功能,先寫測試,用 20% 的時間測 80% 的 bug(或者應該說嚴重度 80%)。

結語

測試是對一個產品成熟度的指標,雖然不是說測試寫得多就一定穩,但起碼可以確保主要的功能都有被保護到,經過測試之後再交付出去的程式,更能夠提升客戶對於產品的信任度。

但很可惜的是,目前台灣看到的軟體專案/公司,有滿多地方其實都沒有在寫測試的,一來 PM 有時程壓力,二來 developer 寫測試的熟練度,也還沒有到能夠跟 PM 報告「請給我時間寫測試!」的地步。

所以,如果公司有機會練習,請好好把握!如果沒機會,就創造機會吧!

邊境的沙漠與極地的雪
在熠熠星光的守護下
前行

參考資料

測試一定要寫好寫滿?時間有限怎麼辦?
Clean Code
The Clean Coder


上一篇
Day 28 - Clean Coder 時程與承諾
下一篇
Day 30 - 從寫對到寫好
系列文
Javascript 從寫對到寫好30

尚未有邦友留言

立即登入留言