SQLite 的作者 Dr. D. Richard Hipp 在 Hacker News 討論了自己對於 SQLite 測試相關的看法:
關於測試覆蓋度,最常見的標准稱為 “modified condition/decison coverage” 或 MC / DC。在像 C語言中,MC / DC 和分支覆蓋雖然不完全相同,但非常接近。
達成 100% MC / DC 並不能證明你總能得到正確的答案。這意味着你的測試非常完善,以至於你設法讓每個機器代碼分支至少在兩個方向上進行。這是一個高標准,很難實現。這並不意味着該軟件是完美的。
但它確實有幫助,而且很大。當我年輕的時候,我曾經認為我可以完美無瑕的代碼。然后我寫了 SQLite,它被許多應用程序拾起並使用。當你的代碼在數十億台設備上的數百萬應用程序中運行時,會出現多少問題。
SQLite 獲得源源不斷的錯誤報告。然后我花了 10個月(2008-09-25 到 2009-07-25)為 SQLite 編寫了 100% 的 MC / DC 測試。之后,錯誤報告的數量減慢到了涓涓細流。還有 bug。但是 bug 的數量大大減少了。100% MC / DC 最初是在 2009-07-25 達成的,但是工作並沒有就此結束。我花費了大部分開發時間來添加和增強測試用例,以跟上可交付的 SQLite 代碼的變化。
100%MC / DC只是一個閾值,一個很高的閾值,一個易於測量且難以作弊的門檻。但它只是我們說“足夠”的門檻。你可以輕松選擇不同的閾值,例如 100% 行覆蓋率。閾值越高,錯誤越少。但只要項目足夠的大,它總會有錯誤。
我的經驗是,你最終必須編寫的奇怪測試只是為了讓一些不起眼的分支以某種方式走向最終在系統中完全不相關的部分並發現問題。 100%MC / DC 的主要好處之一並不是每個分支都經過測試,而是你必須編寫如此多的測試:隨機的、古怪的、錯綜復雜的……然后你就可以發現問題,並修復了許多你從未想過的問題。
100%MC / DC 的另一大優勢是,一旦它們到位,你可以在代碼中的任何地方進行任何更改,如果測試仍然通過,你就會非常自信地沒有破壞任何東西。這使我們能夠以相對較少的逐行檢查,更快地演進 SQLite 代碼。
100%MC / DC 的另一個優點是你真的在測試編譯的機器代碼,而不是源代碼。所以你不用擔心編譯器錯誤。UB(Undefined Behavior)是 C 的一個大問題。即使官方的 C 語言規范不強制要求沒有 UB,我們仍然避免使用 UB。據我們所知,SQLite目前不包含任何 UB,這也就給了我們信心編譯器的結果一定是我們想要的結果。如果你發現了 SQLite 的 UB,請一定告訴我們 :-)
MC/DC(修訂的條件/分支軟件測試)准則是一種實用的軟件結構軟件測試率軟件測試准則,已被廣泛應用於軟件驗證和軟件測試過程中。
案例2-19:MC/DC覆蓋測試。
condition和decision的概念:
if (A || B && C ) { 語句1; } Else{ 語句2; }
A,B,C都是一個條件,而(A || B && C)叫一個Decision,如果是條件軟件測試,只需兩個CASE,就能軟件測試,就是讓這個decision為True和False各一次,就能達到。即:
A=True、B=False、C=True。
A=False、B=True、C=False。
如果是MC/DC,就得4個測試用例,怎么計算呢?
MC/DC覆蓋測試在每個判定中的每個條件都曾獨立影響判定的結果至少一次(獨立影響意思是在其他條件不變的情況下,改變一個條件):
A || B && C
總結:每個條件對結果都獨立起作用。
(1)如果A對結果起作用的話,B必須為False、C必須為True,這樣結果就獨立受A的值影響。(A||0&&1)->(A||0),(A、B、C取值分別為A=True、B=False、C=True和A=False、B=False、C=True)。
(2)同理,如果B對結果獨立起作用,A必須為False、C必須為True,兩種情況B為True、False各一個 (0||B&&1) (A、B、C取值分別為A=False、B=True、C=True和A=False、B=False、C=True)。
(3)如果C獨立對結果起作用,就是讓(A || B) 為True,為了減少用例,上面的用例已經含有這樣的用例了,就取A為False、B為True,這樣C獨立起作用的用例為 (0||1&&C)->(1&&C)。(A、B、C取值分別為A=False、B=True、C=True和A=False、B=True、C=False)。
可以看出,每個條件各走了一次True和False,這樣3個變量條件就會有6個用例, 但是其中里面有兩個是重復的。
在1、2情形中均出現A=False、B=False、C=True。
在2、3情形中均出現A=False、B=True、C=True。
因此,***的測試用例為。
A=True、B=False、C=True。
A=False、B=False、C=True。
A=False、B=True、C=True。
A= False、B=True、C=False。
需要進一步補充說明的是,MC/DC測試的主要目的是為了防止在組合條件表達式中包含副作用(side effect),見以下語句:
if (a() || b() || c()){ ... }
當b函數或c函數產生副作用時,MC/DC軟件測試存在非常大的必要性。
原則上不應在組合條件表達式中調用產生副作用的函數。
參考:
MC/DC(修訂的條件/分支軟件測試)覆蓋測試 - https://book.51cto.com/art/201708/549277.htm
如何看待sqlite作者放棄sqlite4的開發,說使用LSM Tree是一種失敗? - https://www.zhihu.com/question/67858225/answer/632339756