軟件工具的自動化測試總是需要某種方式來比較該工具的功能與我們期望的功能。例如,測試編譯器通常需要驗證已編譯程序的行為、檢查編譯錯誤消息或分析生成的機器代碼。對于靜態或動態分析工具,這通常涉及檢查工具輸出是否有明確定義的輸入集。
下面介紹了一個為結構覆蓋分析工具的內部測試而開發的框架,其中預期的覆蓋結果在源注釋中表示為注釋。該框架用于驗證該工具是否可用于在航空電子領域具有嚴格認證限制的多個安全關鍵軟件項目。
我們首先總結了需要支持的覆蓋標準和工具輸出格式,然后介紹了我們描述工具預期結果的方案的主要原則,并解釋了與基線輸出進行比較相比的優勢。
覆蓋標準和輸出報告格式
我們需要測試的代碼覆蓋率分析工具支持機載軟件DO-178C認證標準定義的三種覆蓋率標準:Statement Coverage、Decision Coverage和Modified Condition/Decision Coverage,通常稱為MC/DC[ 2]。它產生兩種輸出報告格式:
帶注釋的來源,從要分析的來源生成,行前綴為行號和覆蓋結果指示;
一份文本報告,列出違反需要評估的覆蓋標準的情況。
圖 1 中的摘錄顯示了一個帶注釋的源結果示例,該結果由該工具對僅調用一次的 Ada 函數執行決策覆蓋率評估,其值 X 大于 Max 參數。
【圖1 | 此處顯示的是結構覆蓋分析工具對 Ada 函數執行的決策覆蓋評估的示例注釋源結果。]
每行開頭的信息是顯示覆蓋結果的工具輸出。“-#”文本是原始源中的特殊注釋(Ada 中的注釋以“-”開頭)被框架識別為引入標簽,允許用戶表示預期覆蓋結果的行,稍后將對此進行描述。
在 DO-178C 用語中,布爾表達式(例如控制 if 語句的表達式)稱為決策,實現決策覆蓋需要測試評估每個決策 True 至少一次,False 至少一次,此外還要執行每個源語句。
在手頭的示例中,控制 if 語句的決策僅被評估一次,對于 X 》 Max 的布爾值 False。因此,該決定僅被部分覆蓋,并且從不執行第 4 行的 return 語句。這是由“!”傳達的。和第 3 行和第 4 行的行號旁邊的“-”字符,以及第 6 行的“+”注釋,表明那里的 return 語句的正確覆蓋。
此評估的另一種輸出格式,一個列出與標準相關的覆蓋違規的文本報告,將包括如圖 2 中的消息,其中第一部分是文件名:行號:列號源位置一致帶有帶注釋的源結果。
【圖2 | 此處顯示了結構覆蓋分析工具對 Ada 函數執行的決策覆蓋評估的文本報告中生成的消息。]
陳述基本的預期覆蓋結果
在上一節中,說明了該工具的實際覆蓋結果是什么樣的。接下來將描述測試編寫人員如何指定給定測試場景的預期結果。
該工具的主要目標是讓測試人員使用正在測試的源代碼有效地陳述期望,同時抽象出報告格式細節。它還鼓勵積極思考測試的預期結果應該是什么。
該工具將測試定義為三類源文件的組合:
功能源,這是測試人員想要評估并檢查結果是否符合覆蓋工具要求的代碼;
驅動程序源,以特定方式調用功能代碼,具有精確的覆蓋目標;
和helper sources,它們只是為了完整性而需要的,不需要覆蓋分析。
然后,預期的覆蓋結果在驅動程序源中以特殊格式的注釋表示,指的是功能源中也由特殊格式的注釋標記的行。
前面介紹的 In_Range 示例函數顯示了引入標簽的特殊注釋的實例。例如,“expr_eval”標簽允許表示對決策表達式求值的行。給定的標簽可能出現在多行上。
描述驅動程序源中預期覆蓋結果的特殊注釋是注釋序列,如圖 3 所示,其中“xp”代表“預期”。第一行標記了名為functional-source-filename的功能源的預期結果的開始。/tag1/行聲明了對該源代碼中所有標記為tag1的源代碼行的期望。xp-source-line-note傳達這些行的注釋源輸出格式中預期的覆蓋指示字符(所有行的注釋相同),xp-violation-notes傳達文本報告格式中預期的一組違規消息這些行(所有行的設置相同)。
【圖3 | 此處顯示了用于在示例 Ada 函數上執行的結構覆蓋分析評估的驅動程序源中描述預期覆蓋結果的特殊注釋。]
一個驅動程序源可能包含幾個/tag/行用于給定的功能源和對多個功能源的期望。
在/tag/行上,可以使用短標識符以緊湊的方式表示各種可能的覆蓋指示。例如,“l+”、“l-”或“l!”可用于xp-source-line-note以表示預期的“+”、“-”或“!” 分別在帶注釋的源行上的覆蓋率指示。對于xp-violation-notes,例如,在所有可能性中,“s-”表示預期的“從未執行過的語句”違規,或“dF-”表示“從未執行過的決策結果假”違規。
圖 4 顯示了驅動程序源的草圖,以說明對提供 In_Range 函數(名為 in_range.adb)的源文件進行決策覆蓋測試。此驅動程序實現了之前用于說明輸出報告格式的執行場景,使用 X 》 Max 調用一次 In_Range 函數:
【圖4 | 此驅動程序源草圖說明了對提供 In_Range 函數 (in_range.adb) 的源文件的決策覆蓋測試,其中該函數使用 X 》 Max 調用一次,如上一個評估示例中所示。]
/expr_eval/ 行說明了 in_range.adb 中標記為“expr_eval”的行集的預期覆蓋結果。在示例中,這是對決策進行評估的單行(此特定驅動程序僅對 False 一次),因此注釋行(l!)上的部分覆蓋指示和“決策結果為 True 未執行”違規診斷文本報告(dT-)應該是預期的。
/expr_true/ 和 /expr_false/ 行聲明了標記為“expr_true”和“expr_false”的源行的預期覆蓋結果,選擇這些標簽來表示當決策評估為 True 或 False 時執行的語句的行。用作“expr_false”的xp-violations-notes的“0”表示一個空集,這意味著文本報告中的這些行不會違反預期。這與注釋源格式中“+”的預期一致(l+ 作為xp-source-line-note),對應于行上所有項目的完全覆蓋(在示例中,單個 return 語句單行)由執行場景強制執行。
這些期望與初始示例中顯示的實際結果完全一致;使用結構覆蓋分析工具測試框架,該測試將“通過”。
高級期望
上一節展示了預期工具行為的基本公式示例,無條件并引用整行。然而,允許針對目標標準集的完整測試套件需要開發許多高級功能。
最迫切的需求是在xp-violation-notes中提供精確的源位置,以允許在可以合理地預期該行上的不同項目的不同診斷時引用該行的特定部分。
例如,在評估 MC/DC 時,工具診斷指的是布爾表達式中的特定操作數( DO-178C 術語中的決策中的條件),并且大多數編碼標準允許布爾表達式在同一行上具有多個操作數。測試人員必須能夠指定預期覆蓋診斷的線路上的特定條件。其他條件也有類似的需求,例如,當多個語句共享同一源代碼行時,使用語句覆蓋率,或者當表達式中涉及嵌套決策時,使用決策覆蓋率。
這通過在違規指示符末尾使用以下形式的擴展來支持:“行摘錄”,如以下示例期望行,用于對示例 In_Range 函數進行 MC/DC 評估的假設測試。c!:“X 》= Min”表示我們期望不完整的條件覆蓋診斷 (c!) 指定行的“X 》= Min”部分,這只是決策的第一個操作數(圖 5)。
【圖5 | 此處的示例期望線描述了對先前使用的 In_Range 函數示例的假設測試,其中 c!: “X 》= Min” 表示對該行的“X 》+ Min”部分的不完整條件覆蓋診斷的期望。]
引入了一些其他工具來支持,例如,單個語句跨越多行的情況,對于不同版本的工具或編譯工具鏈的期望不同,或者使用通用驅動程序來評估多個覆蓋標準。確切的細節超出了本文的范圍。
執行模型概述
工具測試框架下的通用執行模型包括關于覆蓋結果指示集的推理,稱為覆蓋注釋。通過結合兩個獨立的方面來處理四種覆蓋筆記對象:筆記來源和筆記適用的輸出格式的種類。
關于音符來源,區分以下幾點:
預期注釋,來自預期結果聲明,以及
發出的注釋,可在該工具生成的報告中找到。
關于輸出格式的種類,定義如下:
行注釋,用于注釋源中的覆蓋指示字符,以及
違規說明,用于在覆蓋文本報告中發現的違規消息。
/tag/ line spec中的xp-source-line-note然后在內部建模為預期的 line note對象。xp-violation-notes被建模為預期的違規注釋對象,并且從工具生成的覆蓋率報告中提取發出的線或發出的違規說明對象。
本質上,測試套件引擎為每個測試執行以下步驟:
解析測試源以構建預期的行和違規注釋集,每個功能源一組。引擎將驅動程序源中的/tag/規范與功能源中的標記行進行匹配,并使用特定種類和源位置信息實例化單個注釋對象。
從源代碼構建可執行文件,執行它,然后針對所需標準運行覆蓋率分析工具,生成覆蓋率報告。
解析報告以構建發出的行和違規注釋集。
將預期的行/違規注釋與發出的注釋匹配并報告差異。當工具已根據評估的標準報告了所有預期的覆蓋率指示并且預期工具報告的所有覆蓋率偏差時,測試通過。
方案的主要特點
該方案的一個重要特征是將測試的覆蓋結果期望從字面上放置在驅動功能代碼如何執行的源中,因此哪些部分被覆蓋以及覆蓋到什么程度。這使得驗證測試代碼所做的事情和相應的預期覆蓋結果之間的一致性變得很方便,并提供了一種直接的機制來通過源代碼中的注釋記錄兩者之間的聯系。
另一個關鍵方面是開發一種專門的語法來描述期望,鼓勵測試作者積極思考預期的結果。這與使用與基線輸出進行比較的方法不同,其中基線通常是通過使用工具生成輸出并驗證輸出是否正確來獲得的。無法在此框架內生成預期結果的規范。
基于 DejaGNU 框架 (www.gnu.org/software/dejagnu) 的一些測試套件變體中使用了類似的想法,例如 GCC 項目 (gcc.gnu.org) 使用的測試套件。
該方法對于測試套件的長期維護也很有趣。首先,報告格式的任何變化都通過對測試套件執行引擎的調整來處理,該引擎非常本地化且控制良好。這與面向基線的框架不同,其中報告格式的更改通常會導致對完整測試基線的調整,當測試庫變大時,這變得乏味且容易出錯。其次,測試源維護也更容易,因為覆蓋預期與指定線路在源中的相對位置完全脫節。例如,可以添加注釋或重新排序子程序,而無需更新預期結果。
該框架的主要缺點是專業化。它目前是為覆蓋分析工具量身定制的,并且代碼只支持最初開發環境的工具。然而,可以在多個方向上進行泛化。例如,已經為 C 語言開發了支持,并且可以根據客戶的需求為其他語言添加支持。當該工具具有命令行界面時,該框架還可以適用于其他覆蓋分析工具。在這方面沒有基本的限制。
抽象能力
允許指定行集的標簽方案提供了比單獨的行命名工具更大的抽象,其中每個特定行都需要通過期望進行機械匹配。實際上,/tag/ lines 中的標簽被解釋為一個正則表達式,因此有很多強大的方法可以構建精細的行集模式,并且仔細選擇標簽可以幫助顯著簡化預期結果的表達。在某種程度上,為測試設計一組標簽可以被視為定義一種非常基本的微語言來指定源代碼行集,從這個角度來看,標簽方案提供了一種元語言,可以為每個測試實例化。
另一個級別的分解是通過在測試之間共享源的能力實現的,特別是對于功能慣用語的不同實現具有一組通用的驅動程序源。
例如,考慮在 Ada 中測試工具在布爾表達式(如“A 然后 B”)上的正確行為的目標。一個自然的起點是最簡單的情況,其中 A 和 B 是簡單的布爾變量,具有如圖 6 所示的功能代碼。
【圖6 | 此處顯示的是使用 Ada 語言中的簡單布爾表達式“A and then B”對結構覆蓋分析工具的行為進行的示例測試。]
為了練習圖 6 中的代碼,可以編寫一些驅動程序,以不同的方式直接調用 Eval_Andthen 過程,一次或多次,將不同的值傳遞給 A 和 B,并相應地說明預期結果。
人們意識到,對于具有比基本布爾變量更復雜的操作數的功能代碼,額外的測試將是有意義的。如果這些測試是作為獨立實體編寫的,從作為模型的基本案例開始,幾乎可以立即看出所需的驅動程序源集與第一次編寫的非常相似;只需以不同的方式調用功能代碼并具有相同的覆蓋預期。
相反,可以設置一個環境,其中針對一種操作數的每組測試都提供了一個幫助 API,驅動程序代碼始終可以以相同的方式使用該 API,而不管實際操作數的種類如何。圖 7 中的驅動程序代碼提供了一個示例,其中 FUAND 代表“Functional And”。幫助程序包預計將提供一個“Eval_TT_T”子程序,該子程序調用功能代碼,安排兩個操作數評估 True (_TT_),因此決策也評估 True(尾隨 _T):
【圖7 | 此處顯示的示例驅動程序代碼使用了一個輔助 API,無論操作數的類型如何,該 API 始終可以以相同的方式使用,其中“Eval_TT_T”子程序調用功能代碼以啟動兩者對 True (_TT_) 和 (_T) 的評估操作數。]
為新的操作數類型組合添加測試只需要提供功能代碼和幫助程序包,并且添加驅動程序源會自動使所有已經存在的操作數類型變體受益。這是一個非常強大的機制,甚至可以進一步推廣以支持在一般上下文中對決策進行覆蓋評估,而不僅僅是作為 if 語句中的控制表達式。
總結和觀點
作為開發覆蓋分析工具內部測試框架的一部分,我們設計了一種方法,其中對覆蓋結果的期望在測試源中表示為特殊注釋。此處概述了這些方案的一些重要方面。所描述的框架鼓勵積極思考每個測試的預期結果應該是什么,并提供允許對開發和維護工作進行分解的抽象設施。
所描述的方法是我們 GNATcoverage 工具認證的基礎,這些項目使用該工具作為航空電子領域 DO-178B 和 DO-178C 認證的一部分,達到最嚴格的認證級別,這需要 MC/DC。基于這項工作,我們正在評估可能的方法來形式化覆蓋分析問題的測試策略的各個方面,特別是關于適當的 MC/DC 測試對表達式拓撲、表達式上下文以及操作數的種類和復雜性的影響。
審核編輯:郭婷
-
API
+關注
關注
2文章
1485瀏覽量
61814 -
代碼
+關注
關注
30文章
4747瀏覽量
68349
發布評論請先 登錄
相關推薦
評論