FEAT
FrontEnd Automates Test 前端全自動化測試
序章
文章開頭先引一個知乎上的問答:如何進行前端自動化測試?
我相信做過前端的朋友都有這個疑問。希望這篇文章裏你能看到一些別人的測試方法,幫助你更好的進行測試工作;
很尷尬的是,在此之前我的開發測試也都不會有單元測試而都是人肉測試,對不起自己 ☹️;
為了以後能夠更好的進行測試工作,記錄自己測試學習的過程,希望能幫自己也能幫到別人。
做測試,應該從哪裏開始切入呢
做測試的倆個要素
- 程序:我們往常寫的代碼
- 測試用例:測試你的代碼的輸入輸出是否符合預期
一個簡單的測試
假如有這樣一個倆數相加的程序功能:
function add(a, b){
return a+b
}
我們現在要對這個倆數相加的程序功能進行測試,來測試這個 add 方法的輸入輸出是否符合我們的預期,那就要去寫測試用例去測試。
那麼我們的測試用例怎麼寫呢
方式一:你可能這麼寫
5 === add(2, 3) // 測試用例(1)
(1.7976931348623157e+308 * 2) !== add(1.7976931348623157e+308, 1.7976931348623157e+308 + 1) // 測試用例(2)
測試用例(1)用預期的 5 和 add 方法輸入 2 和 3 的輸出結果進行比對,是否相等;如果相等,那麼 add 方法就通過測試用例,如果不等,就證明我們的 add 方法存在問題。
可以看到測試用例(1)
結果是相等,通過測試
測試用例(2)用預期的 1079654173767686669 和 add 方法輸入 1.7976931348623157e+308 和 1.7976931348623157e+308 的輸出結果進行和用例(1)一樣的操作。
可以看到測試用例(2)
結果應該不等, 測試不通過
原因:原來是我們沒有考慮大數相加結果溢出的情況,所以我們的 add 方法是隻能在相加的結果不會溢出情況下得到期望的正確結果。
我們就有必要對我們的方法進行改動以適配大數相加,那麼每一次這個方法的改動,我們就要執行一次上面的測試用例。這樣我們就能進行我們的而測試工作了。
如果應對簡單的需求這樣的方式顯然夠用了,但是事實上應該是沒人會這麼寫測試用例的。
大家會用 nodejs 提供的 assert 模塊或者 shouldjs 這類斷言庫來幫我們做斷言這件事情;而且這些模塊被 node 原生提供支持,後面要在此測試基礎上進行自動化測試,生成測試報告之類的,都非常方便。
下節我們以 assert 模塊為例來改造這個測試用例;這一節我們先做一些準備工作,要寫測試用例,會用到斷言,那麼我們這節就先看看斷言的相關內容,以 node 的 Assert 模塊為例:
Assert 模塊
assert 模塊提供了斷言測試的函數,用於測試不變式。
assert.AssertionError 類
Error 的一個子類,表明斷言的失敗。 assert 模塊拋出的所有錯誤都是 AssertionError 類的實例。
這是我們寫測試用例,執行測試,調試測試過程最常見到的一個類,指示遇到斷言失敗。
assert構造函數
assert(value[, message])
assert.ok() 的別名。
assert.deepEqual(actual, expected[, message]) 已廢棄
附:assert.deepStrictEqual() 的別名。
deepStrictEqual
assert.deepStrictEqual(actual, expected[, message])
測試 actual 參數與 expected 參數是否深度相等。 深度相等意味着子對象中可枚舉的自身屬性也會按以下規則遞歸地比較。
assert.deepStrictEqual({a:1}, {a:1}); //這樣的測試是可以通過的
注意:腳本中這倆個是不絕對相等的
doesNotReject
assert.doesNotReject(block, error)
該函數相當於 assert.doesNotThrow(),除了需要等待完成的異步特性。
等待 block 的 promise 完成,如果 block 是一個函數,則立即調用該函數並等待返回的 promise 完成,然後檢查 promise 是否被 reject。
如果 block 是一個函數且同步地拋出一個錯誤,則 assert.doesNotReject() 會返回一個被 reject 的 Promise 並傳入該錯誤。 如果該函數沒有返回一個 promise,則 assert.doesNotReject() 會返回一個被 reject 的 Promise 並傳入 ERR_INVALID_RETURN_VALUE 錯誤。 以上兩種情況都會跳過錯誤處理函數。
doesNotThrow
assert.doesNotThrow(block, error)
斷言 block 函數不會拋出錯誤。
當 assert.doesNotThrow() 被調用時,它會立即調用 block 函數。
如果拋出錯誤且錯誤類型與 error 參數指定的相同,則拋出 AssertionError。 如果錯誤類型不相同,或 error 參數為 undefined,則拋出錯誤。
assert.equal(actual, expected[, message]) 已廢棄
附:assert.strictEqual() 的別名。
fail
assert.fail([message])
拋出 AssertionError,並帶上提供的錯誤信息或默認的錯誤信息。 如果 message 參數是 Error 的實例,則會拋出它而不是 AssertionError。
assert.fail(actual, expected[, message[, operator[, stackStartFunction]]]) 已廢棄
附:使用 assert.fail([message]) 代替。
ifError
assert.ifError(value)
如果 value 不為 undefined 或 null,則拋出 value。 可用於測試回調函數的 error 參數。 堆棧蹤跡會包含傳入 ifError() 的錯誤的所有幀,包括潛在的 ifError() 自身新增的幀。
assert.notDeepEqual(actual, expected[, message]) 已廢棄
附:使用 assert.notDeepStrictEqual() 代替。
notDeepStrictEqual
assert.notDeepStrictEqual(actual, expected[, message])
測試 actual 參數與 expected 參數是否不深度全等。 與 assert.deepStrictEqual() 相反。
附:assert.notStrictEqual() 的別名。
assert.notEqual(actual, expected[, message]) 已廢棄
附:使用 assert.notStrictEqual() 代替。
notStrictEqual
assert.notStrictEqual(actual, expected[, message])
使用 SameValue 比較法測試 actual 參數與 expected 參數是否不全等。
ok
assert.ok(value[, message])
測試 value 是否為真值。 相當於 assert.equal(!!value, true, message)。
rejects
assert.rejects(block, error)
等待 block 的 promise 完成,如果 block 是一個函數,則立即調用該函數並等待返回的 promise 完成,然後檢查 promise 是否被 reject。
如果 block 是一個函數且同步地拋出一個錯誤,則 assert.rejects() 會返回一個被 reject 的 Promise 並傳入該錯誤。 如果該函數沒有返回一個 promise,則 assert.rejects() 會返回一個被 reject 的 Promise 並傳入 ERR_INVALID_RETURN_VALUE 錯誤。 以上兩種情況都會跳過錯誤處理函數。
strictEqual
assert.strictEqual(actual, expected[, message])
使用 SameValue 比較法測試 actual 參數與 expected 參數是否全等。
throws
assert.throws(block, error)
斷言 block 函數會拋出錯誤。
至此,斷言模塊所有的 api 我們都清楚了,當然 node 官網對於Assert 模塊還有更詳細的內容。