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