TESTCOV:可靠的測試套件執行和覆蓋率度量


TESTCOV:可靠的測試套件執行和覆蓋率度量

引用

Dirk Beyer, Thomas Lemberger, TESTCOV: Robust Test-Suite Execution and Coverage Measurement, 34th IEEE/ACM International Conference on Automated Software Engineering (ASE), 2019, 1074-1077

摘要

在本文中我們介紹了 TESTCOV,這是一種用於在 C 程序上進行可靠的測試套件執行和測試覆蓋率測量的工具。 TESTCOV 在隔離的容器中執行程序測試,以確保系統完整性和可靠的資源控制。 該工具提供每個測試以及整個測試套件的覆蓋率統計信息。 TESTCOV 使用基於 XML 的簡單交換格式並以 Test-Comp 創建的標準規範約束測試套件。TESTCOV 已成功用於 Test-Comp’19,對 1720 個不同的程序執行近 900 萬次測試。 TESTCOV 的源代碼在開放源代碼許可 Apache 2.0 下發布,可從https://gitlab.com/sosy-lab/software/ test-suite-validator 獲得。包括演示視頻在內的完整內容,請訪問https://doi.org/10.5281/zenodo.3418726。

關鍵詞:測試執行,覆蓋率,測試套件規約

1.介紹

現代的測試用例生成器能夠生成系統測試用例,以前所未有的方式揭示程序中的錯誤,但是執行這些測試可能會導致系統故障,修改,信息洩漏或資源耗盡。 因此,程序測試通常在虛擬機或容器(例如 Docker)中執行。 TESTCOV 為此提供了一個輕量級的解決方案:它基於現有的基準測試工具 BENCHEXEC,使用覆蓋文件系統和 Linux 控制組來保護文件系統免受修改,並防止在測試執行期間意外使用資源。 與其他容器化技術相比,BENCHEXEC 在使用過程中不需要安裝任何其他軟件或超級用戶特權,因為它僅依賴於 Linux 內核中內置的功能。 TESTCOV 提供每個測試以及整個測試套件的行覆蓋,分支覆蓋和條件覆蓋的覆蓋率統計信息,並創建圖以可視化所測得的數據。

TESTCOV 已在第一次軟件測試國際競賽(Test-Comp’19)中使用,驗證所有 9 位參與者創建的測試套件。 TESTCOV 使用簡單的基於 XML 的交換格式進行測試套件規範,該格式由 Test-Comp 建立標準。 所有 9 位參與者都支持交換格式。 過去,測試用例生成器使用專有格式來輸出其生成的測試,這導致了兩個問題:根據格式的不同,測試套件通常只能使用輔助程序執行或根本不執行,並且由不同測試用例生成器生成的測試套件不能直接進行比較或組合。 基於 XML 的交換格式解決了這些問題。

可獲得:TESTCOV 以壓縮包的形式在 gitlab 上公開。

相關工作:TESTCOV 旨在統一和執行由測試用例生成器為 C 程序創建的測試套件。 KLEE 提供了一個重放庫,該重放庫可用於從被測程序創建測試工具,利用該庫可以執行 KLEE 專有的測試用例格式的單個測試。 由 AFL-FUZZ2 創建的測試用例可以直接輸入程序。 現有的測試執行器都不支持其他測試用例生成器創建的測試,也不支持完整的測試套件的執行。TESTCOV 基於 BENCHEXEC; 其他用於容器化的工具是 Docker3,LXC4 和 Snap5。 BugZoo6 以及 ManyBugs 和 IntroClass 基準測試是與軟件 Bug 隔離和可靠執行有關的其他項目。

2.TESTCOV 的結構

圖 1 顯示了 TESTCOV 的輸入和輸出。 TESTCOV 獲得測試中的 C 程序,要檢查的覆蓋率標準和測試套件的輸入,並創建一個可執行程序,該可執行程序可用於向測試中的程序提供測試,有關測試套件的覆蓋率統計信息以及與原始測試套件相同的覆蓋範圍(就覆蓋標準而言)的規約後的測試套件。

TESTCOV:可靠的測試套件執行和覆蓋率度量

圖 1 TESTCOV 的輸入與輸出

A. 測試套件交換格式

TESTCOV 以基於 XML 的測試套件交換格式讀寫測試套件,該測試套件包括兩部分:元數據文件和一組測試用例文件,每個定義一個測試用例。元數據文件是描述測試套件的 XML 文件,並且始終命名為 metadata.xml。圖 2 顯示了具有所有可用字段的示例元數據文件。一些值得注意的字段是:被測程序的編程語言(),為測試套件創建的覆蓋標準(),被測程序的 SHA-256 哈希(),測試套件測試的程序功能(),以及為其創建程序測試的系統結構()。如果測試套件是另一個測試套件的結果,例如,由於測試套件減少,則還可以記錄此輸入測試套件的文件名()及其 SHA256 哈希()。一個測試用例文件(圖 3)包含描述輸入值序列的一系列標籤。測試套件的目錄結構是任意的,它們由 TESTCOV 作為 zip 文件提供並由其創建,以實現高效存儲和便捷處理。由於在 Test-Comp 中使用了交換格式,因此許多測試用例生成器都支持以下格式:COVERITEST,CPA-TIGER7,ESBMC,FAIRFUZZ,KLEE,PRTEST,SYMBIOTIC 和 VERIFUZZ。

TESTCOV:可靠的測試套件執行和覆蓋率度量

圖 2 測試套件元數據文件示例

TESTCOV:可靠的測試套件執行和覆蓋率度量

圖 3 測試套件測試用例示例

B.測試執行

為了執行測試,被測程序是根據測試工具編譯的幷包含以下兩個部分:(1)用於接收測試值的方法 getinput,以及(2)針對測試程序中委派給 getinput 的每種輸入方法的新定義。

方法 get_input 從標準輸入中以 C 格式字符串讀取測試輸入,並將其解析為 C 類型。 它支持所有原始類型(最大為 long double)的十六進制(例如 0x4a),整數(例如 74),浮點數(例如 74.5)和字符表示形式(例如'J')以及單行字符串輸入。 使用 C 標準庫中的方法進行解析。

對於每種輸入方法,都會引入一個新定義,該定義使用輸入方法返回類型的相應格式類型調用 get_input。 例如:

TESTCOV:可靠的測試套件執行和覆蓋率度量

給定一個測試套件,TESTCOV 首先解析元數據文件,以檢查與輸入文件和覆蓋標準的一致性。 如果其中之一不一致,則會通知用戶。 然後,TESTCOV 遍歷所有測試用例文件,讀取每個測試的測試輸入,執行編譯的程序,然後通過標準輸入順序傳入測試輸入並執行。

為確保測試執行不會因非終止測試而停滯,對每個測試執行都設置了時間限制。 另外,如果一個測試用例包含的輸入值比必要的少,一旦所有輸入值被消耗並且請求一個新的輸入值,TESTCOV 將終止執行。

為了確保測試執行不會改變用戶的系統,執行惡意操作或相互影響,TESTCOV 使用 RUNEXEC8(BENCHEXEC 的一部分提供了此工具)將每個測試執行隔離在單獨的容器和控制組中。 我們對其進行配置,使容器中的測試執行無法訪問網絡,無法查看或修改其他系統進程,並且可以在可防止原始系統中文件修改的覆蓋文件系統上工作。 寫入容器內的文件保留在內存中,而不寫入磁盤。 在存在文件操作的情況下,將所有文件修改保存在內存中還可以加快測試的執行速度。 Cgroup 是 Linux 內核的一項功能,它可以限制和衡量一個進程及其所有子進程的資源消耗。 TESTCOV 使用它來將內存使用量限制為用戶指定的最大值,將計算限制為指定數量的 CPU 內核,並對測試執行施加時間限制。

圖 4 顯示了具有副作用的程序。 程序採用單個字符作為輸入,這裡通過 Test-Comp-specific 方法__VERIFIERnondetchar。 如果輸入為“ a”,則會產生一個 fork 隱患,它會產生無數個進程,這些進程最終將填滿用戶系統的進程表並使其無法使用。 如果輸入不為“a”,程序將刪除一些文件,並檢查刪除是否成功。 如果為 TESTCOV 提供了一個定義兩個分支的測試用例的測試套件,它將正確執行兩個分支,但是進程數受到限制(默認為 5000 個進程),並且文件刪除僅在執行的容器中發生,而不是在原始文件系統中,因此,在覆蓋範圍測量仍然準確的情況下,不會對用戶系統造成損害。

TESTCOV:可靠的測試套件執行和覆蓋率度量

圖 4 產生副作用的程序示例

C.覆蓋統計信息

TESTCOV 提供每個測試和整個測試套件的覆蓋率信息,併為覆蓋率標準創建圖。 TESTCOV 在查詢語言 FQL 中讀取覆蓋率標準。當前,它支持塊覆蓋,分支覆蓋和條件覆蓋,以及對錯誤函數的調用覆蓋。為了計算覆蓋率,TESTCOV 使用 GCC 和 LCOV。 LCOV 將每個行的覆蓋範圍和程序條件存儲在一個跟蹤文件中。 LCOV 聲稱要存儲分支覆蓋信息,但將短路布爾運算的每個條件視為一個單獨的分支。例如,圖 6 中的代碼包括兩個分支:如果條件 x > 0 || x < 0 為真,則進入 if 分支,否則進入 else 分支。 LCOV 將兩個條件 x> 0 和 x <0 的每個判斷視為一個單獨的分支,因此報告該程序有四個分支。對於該程序,第一個條件(x> 0)的求值始終為 true,因此每個程序執行都使用 if 分支。由於從未評估條件 x <0,因此 LCOV 報告的分支覆蓋率僅為 25%,而不是預期的 50%。為了避免這種情況並執行正確的分支覆蓋率測量,TESTCOV 在程序的每個程序分支的開頭添加了程序標籤 BRANCH_i(圖 7),並使用 LCOV 的行覆蓋率測量來檢查添加的哪些程序標籤被覆蓋了。這樣,TESTCOV 可以準確地測量分支覆蓋範圍。

默認情況下,LCOV 僅將所有程序執行的累積覆蓋範圍存儲在一個跟蹤文件中。為了獲得累積的覆蓋率和每個單獨的測試用例的單獨覆蓋率,TESTCOV 使用 LCOV 管理兩個單獨的跟蹤:一個默認跟蹤,它是為每個測試執行新創建的,並且僅存儲該執行的覆蓋範圍,而另一個包含累積所有測試執行的覆蓋信息。雖然每個測試的覆蓋率信息通常對於執行測試沒有太大的幫助,但它可以為測試套件的優化和簡化提供啟發。 TESTCOV 以圖表和 CSV 文件的形式提供覆蓋率統計信息,可以輕鬆地對其進行進一步處理。它提供了一個圖(圖 5),該圖顯示:(a)執行測試套件的第 n 個測試(x 軸)後的累積測試覆蓋率(y 軸)(圖中的實線)。 5),以及(b)每個測試用例的測試範圍(圖 5 中的條形)。圖中測試的順序始終與執行順序相同。可以看到,例如,覆蓋率達到 75.0%的五個測試包含了覆蓋率達到 12.5%的三個測試,因為在執行了任何執行之後,累積覆蓋率不會增加到 75.0%和 87.5%以上。此外,很明顯,只需執行第 6 個測試即可達到與該測試套件的所有 9 個測試一起獲得的相同分支覆蓋率,因為它自身提供的覆蓋率與整個測試套件的累積覆蓋率相同。

TESTCOV:可靠的測試套件執行和覆蓋率度量

圖 5 獨立和累積測試覆蓋率

TESTCOV:可靠的測試套件執行和覆蓋率度量

TESTCOV:可靠的測試套件執行和覆蓋率度量

​ 圖 6 短路分支代碼 圖 7 用於計算分支覆蓋率的代碼

D. 測試套件規約

TESTCOV 通過策略模式實現了測試套件規約,因此可以在現有基礎架構中添加不同的算法以減少給定的測試套件。默認情況下,TESTCOV 提供以下測試套件規約技術:如果覆蓋標準是要涵蓋對錯誤函數的調用,則 TESTCOV 會創建一個新的測試套件,其中包括覆蓋該錯誤功能的原始測試套件中的一個測試用例。如果覆蓋範圍的標準是覆蓋行,分支或條件,則 TESTCOV 創建一個新的測試套件,該套件可能小於原始測試套件,並且可以實現相同的覆蓋範圍。為此,它會在每次測試執行後讀取記錄的累積覆蓋率,並且只有在其相應的測試執行增加了累積覆蓋率的情況下,才將測試添加到規約測試套件中。 TESTCOV 以任意順序執行測試,因此此方法不一定會產生最小的測試套件,但是不需要其他附加測試執行或計算,使得該規約方法是簡單而有效的。

3.使用

安裝:TESTCOV 需要 Python 3.6 或更高版本。 以下命令行將安裝 TESTCOV 及其依賴項(從 TESTCOV 源代碼的基本目錄執行):

> python3 setup.py install

執行:TESTCOV 通過命令行啟動,帶有三個必需的參數:(1)–test-suite 指定要執行的測試套件,(2)–goal 指定覆蓋標準,以及(3)程序文件。 測試套件以 zip 文件的形式提供,覆蓋標準以 FQL 語法的文本文件的形式提供。 以下示例命令行在測試套件 suite.zip,覆蓋標準 criteria.prp 和程序 prog.c 上運行 TESTCOV:

> testcov –test-suite suite.zip –goal criterion.prp prog.c

輸出目錄中將包含所有輸出文件,即可執行測試工具,簡化的測試套件,覆蓋率統計信息和圖表(以 SVG 格式)。

由於要執行額外的文件系統操作,因此為每個測試執行和覆蓋率度量創建單獨的容器會增加執行開銷。 TESTCOV 提供了可選參數,以在不需要這些功能時將其關閉。 以下命令行顯示所有此類參數:

> testcov –help

測試格式自適應:為了使測試用例生成器易於適應基於 XML 的測試格式,我們提供了一個名為 tsbuilder9 的小型 Python 庫。 它可用於以已建立的測試套件交換格式創建測試套件元數據和測試用例。

4.應用

TESTCOV 已用於 Test-Comp’19,它在 9 個不同的測試用例生成器上針對 1720 個不同的程序和 2 個不同的覆蓋率標準運行了將近 900 萬個測試。 TESTCOV 在比賽期間用於執行和覆蓋率度量。 競賽的所有結果均可在線獲得。顯示幾個測試用例生成器或元類別(例如 Cover-Branches)的結果的表格僅列出了 TESTCOV 計算的覆蓋率。 單個測試生成器和子類別的表格(例如 coverage-branches.ReachSafety-Arrays-VERIFUZZ11)提供了完整數據,包括累積測試覆蓋率的精簡版圖表。

5.結論

TESTCOV 是用於在 C 程序上執行測試套件的工具,它以 Test-Comp 的簡單和標準交換格式讀取測試套件,並執行可靠的測試執行。 TESTCOV 使用 BENCHEXEC 作為基礎,用於隔離執行的容器和操作系統內核提供的資源控制的控制組。當前版本提供了四個重要覆蓋標準的獨立和累積覆蓋統計信息。 TESTCOV 已成功用於執行 Test-Comp’19。 儘管 TESTCOV 是針對 C 程序實現的,但是所使用的概念可以輕鬆地轉換為其他語言。

致謝

本文由南京大學軟件學院 2020 級碩士生曹振飛翻譯轉述。

感謝國家重點研發計劃(2018YFB1003900)和國家自然科學基金(61832009,61932012)支持!


分享到:


相關文章: