劉 輝,楊永凱,劉中一
(1.民航旅客服務智能化應用技術重點實驗室,北京 101318;2.中國民航信息網絡股份有限公司,北京 101318)
近年來,隨著業務復雜度的不斷提升,高效、可靠地保障企業級軟件質量,杜絕各種運營事故和安全風險,是所有企業面臨的嚴峻挑戰。眾所周知,軟件質量會影響項目的進度、成本和范圍,最終影響客戶對企業的信賴。因此,企業對軟件質量的要求日益增高。為了保證軟件質量,在開發過程中引入了多種軟件測試技術[1-2]。目前國內公司主要是以功能測試為主,功能測試的技術手段又以手工測試為主,而自動化測試是在手工測試之后進行的,主要用于回歸測試階段。自動化測試是軟件測試活動中一個重要的分支和組成部分,即利用工具或腳本達到測試目的,沒有人工或者極少人工參與的軟件測試活動稱為自動化測試。自動化測試可以方便地進行回歸測試,尤其是在敏捷開發過程中,版本快速迭代,自動化測試更具優勢[3-4];自動化測試可以提升效率,減少重復工作,節省人力成本,讓測試人員可以做更多有意義事情,比如探索性測試[5]等;自動化測試可以保證每次測試的完整性和一致性,發現更多隱藏問題。
軟件系統中的多種功能維度[6]會在生產業務的推動下,演變出各種功能點的組合。自動化測試需要完備的功能測試用例庫[7-8],業界已經有大量人員研究測試用例生成方法[9-11]。
本文第2部分首先分析了手工構造測試用例的基本方法;然后提出了精簡與自動生成測試用例方法,主要思想是根據業務場景分類業務數據,構造功能點組合矩陣,歸并、精簡業務場景之間的功能點組合矩陣,再執行生產請求,匹配功能點組合矩陣,自動生成測試用例;最后舉例說明精簡與自動生成測試用例方法。第3部分介紹了精簡與自動生成測試用例方法的實際應用效果。文章最后對提出的精簡與自動生成測試用例方法進行了總結性的討論。
測試用例包含測試數據、測試請求、期望結果。構造測試用例的基本方法如圖1所示。

圖1 手工構造測試用例流程
(1)在完成功能需求分析后,測試人員根據功能需求設計測試用例,其中主要是設計測試數據、測試請求以及期望結果。
(2)測試人員根據測試用例的設計文檔,手工構造測試數據,依據測試數據構造相應的測試請求和期望結果。
(3)在正式測試前,需要利用現有的軟件調試測試用例,如果返回結果與期望結果一致,代表測試用例正確,可以納入到測試用例庫中;如果返回結果與期望結果不一致,需要分析測試用例中的測試數據、測試請求和期望結果,判斷哪個部分錯誤,并修正相應的內容。對修正后的測試用例再次執行,直到測試用例正確為止。
上述測試用例的構造過程全部由人工完成,需要產品、開發、測試互相配合,耗費人力和時間成本巨大,而且覆蓋功能點范圍有限。隨著業務的飛速發展,軟件中的多種功能維度會在實際業務的推動下,演變出各種功能的組合,由于開發和測試環節,對業務的敏感度較低,很難快速響應業務變化,識別并構造出符合實際業務的測試用例。
針對上述軟件測試過程中手工構造測試用例的問題,本文提出了一種測試用例精簡與自動生成方法。將業務數據按照業務場景分類,構造功能點組合矩陣,歸并、精簡業務場景之間的功能點組合矩陣,減少冗余的測試用例,再執行生產請求,匹配功能點組合矩陣,自動生成測試用例。從而達到聚焦核心功能點、提升軟件的代碼測試覆蓋率,實現提升軟件質量和安全、降低人工成本、提升團隊交付能力的目的。
2.2.1 功能點組合矩陣構造
在真實的生產環境中,用戶通常會預定義一系列的業務場景,業務場景通過功能點組合構建而成,不同的業務場景包含不同的功能點組合。
定義1:功能點組合矩陣。假設某一業務場景包含n個功能點F={f1、f2、...、fn},任一功能點fi的取值集合記為C(fi),功能點組合矩陣是所有功能點取值集合的笛卡爾積,記為A。

功能點組合矩陣的每一行是n元組n-T=(c1,c2,...,cn),其中每個元素即為對應功能點的一種取值。功能點組合矩陣A包含n-T的數量記為|A|。

定義2:標簽。一個軟件會包括多種業務場景,不同的業務場景相互獨立,涉及不同的功能維度,即不同的功能點組合,因此不同的業務場景對應不同的功能點組合矩陣。在每種業務場景下,用戶發布一批業務數據,用以描述該業務場景的各種適用條件,并通過一個或多個屬性標識出業務數據所屬的業務場景,這些屬性稱為標簽D。
本文通過標簽D將業務數據劃分在不同的業務場景下,根據業務場景涉及到的功能點F,提取出業務場景的元組T,分析業務場景下各功能點的取值集合C,構造功能點組合矩陣A。
2.2.2 測試用例精簡
定義3:測試子集,測試超集。假設存在2個業務場景的功能點組合矩陣A1和A2,其功能點分別為F1和F2,若

則,A1是A2的測試子集,A2是A1的測試超集,記為A2→A1。
定理1:2個業務場景的功能點組合矩陣A1和A2,若A1是A2的測試子集,則|A1| ≤|A2|。
證明:2個業務場景的功能點組合矩陣A1和A2,其功能點分別為F1和F2,A2→A1。
根據定義3,F1?F2,|F1|≤|F2|,假設n1=|F1|,n2=|F2|,n1≤n2;
又根據定義3,?f∈F1∩F2,C1(f)?C2(f),|C1(f)|≤|C2(f)|;

證畢。
定理2:測試超集測試通過,其測試子集必然測試通過。
證明:2個業務場景的功能點組合矩陣A1和A2,其功能點分別為F1和F2,A2→A1。
測試超集測試通過,則?f∈F2,功能點f測試通過。
假設測試子集測試不通過,則?f∈F1,功能點f測試不通過。根據定義3,f∈F2,功能點f測試不通過,與前提條件不一致。因此,假設不成立,測試子集測試必然通過。
證畢。
本文所提測試用例精簡方法,主要采用降維和歸并2種策略,具體描述如下:
(1)降維。假設全業務功能點組合矩陣H包含m個功能點E,將業務數據按照業務場景劃分后,某業務場景的功能點組合矩陣A包含n個功能點F。根據定義3,業務場景的功能點組合矩陣是全業務功能點組合矩陣的測試子集,H→A,F?E,n≤m,根據定理1,|A|≤|H|。
在軟件中,通常采用關系型數據庫保存業務數據,所有業務場景的業務數據融合在相同的表空間中,共享相同的數據表,因此數據表擁有所有業務場景涉及到的功能點字段。盡管在技術上按照業務類別將功能點字段劃分在不同的表中,可是相對于某一確定的業務場景,仍然會有多余的功能點字段。通過劃分業務場景,可以避免全功能點組合,在不失測試完備性的前提下,有效地對業務數據降維[12],減少每種業務場景的功能點組合矩陣元組數量,從而精簡測試用例[13-15]。
(2)歸并。假設存在2個業務場景的功能點組合矩陣A1和A2,其功能點分別為F1和F2,A1是A2的測試子集A2→A1。根據定義3,F1?F2,根據定理2,A2測試通過,A1必然測試通過。
軟件中不同的業務場景之間存在著相似性,甚至內容相同,只是定義的標簽不同。如果某個業務場景涉及到的功能點字段包含另一個業務場景涉及到的功能點字段,并且相同功能點字段在該業務場景中的取值集合包含在另一個業務場景中的取值集合,只需要測試該業務場景即可。因為該業務場景涉及到的功能點字段更全,取值范圍更廣,囊括了另一個業務場景的各種情況。通過歸并業務場景,可以剔除冗余的業務場景,避免重復測試,減少冗余的測試用例,達到精簡測試用例的目的。
2.2.3 測試用例自動生成
本測試用例自動生成方法是侵入式的,需要在現有軟件中打樁,記錄軟件的執行路徑,將相關信息以結構化的形式進行存儲。此外本方法還依賴于海量的業務數據和生產日志,需要在其中篩選出符合業務場景測試需求的用例。下面將介紹該方法的實現步驟。
輸入:業務數據
生產日志
輸出:測試用例集
(1)初始化測試用例集為空集。
(2)構造精簡的功能點組合矩陣,定義測試需求。
(3)基于打樁程序框架,在軟件的功能點實現打樁功能。
(4)執行生產日志中的請求,篩選并構造測試用例。
(5)遍歷生產日志。基于打樁后的軟件程序和業務數據,執行每一條生產日志請求;打樁程序記錄各個功能點的執行信息,包括功能點的名稱、請求參數、業務數據內容,以及處理結果等信息;提取并分析各個功能點的執行信息,識別執行到的功能點;匹配測試需求,如果該生產日志請求的執行路徑首次覆蓋到的功能點組合矩陣的某一元組,將此生產日志請求存入測試用例庫。
(6)直至滿足測試需求的完備性,結束遍歷。本方法采用真實的業務數據和生產日志作為輸入。業務數據是用戶根據自身的業務發展情況創建的,最能體現用戶的真實業務意圖。而生產日志中的請求是用戶根據自身的需要發起的,最能體現用戶的真實使用意圖。因此,生產日志請求和涉及的業務數據,構成了最有價值的測試用例。
匹配測試需求,即匹配功能點組合矩陣。執行每個生產日志請求,將其執行的功能點組合與業務功能點組合矩陣中的每一元組比較,如果生產日志請求執行的功能點組合能夠覆蓋業務功能點組合矩陣的某一元組,并且之前沒有被覆蓋過,則將該生產日志請求納入到測試用例庫中,作為測試請求。
打樁程序框架采用外掛模式,對每個功能點增加打樁功能程序,以及打樁開關選項,控制功能點是否執行打樁程序。當需要采集某個功能點的執行信息時,只需要在配置中動態打開該功能點的打樁開關,便可獲取到相應的執行信息。打樁程序可以按照軟件系統的功能層次記錄執行情況,假設在功能A中調用了功能B,則打樁程序的記錄結果與之對應,在執行結果A中包含執行結果B的內容。
2.2.4 舉例說明
假設某軟件有5個功能點,劃分為3個業務場景后,各業務場景包含的功能點和取值集合如下:
業務場景一:
功能點1:{a11,a12,a13};功能點2:{b11,b12};功能點3:{c11,c12};功能點4:{d11}。
業務場景二:
功能點1:{a21,a22};功能點4:{d21};功能點5:{e21,e22}。
業務場景三:
功能點1:{a11,a13};功能點3:{c11,c12}。
上述3個業務場景對應的功能點組合矩陣見表1—表3。

表1 業務場景一功能點組合矩陣

表2 業務場景二功能點組合矩陣

表3 業務場景三功能點組合矩陣
由定義3,業務場景三功能點組合矩陣是業務場景一功能點組合矩陣的測試子集,又由定理2,業務場景三功能點組合矩陣可以被精簡掉。因此,業務場景一和業務場景二的功能點組合矩陣構成了該軟件的測試需求。
遍歷生產日志中的請求,針對業務場景一,打開功能點1、功能點2、功能點3、功能點4的打樁開關,記錄每個生產日志請求的執行情況。假設某一生產日志請求執行了功能點1、功能點2、功能點3、功能點4,對應的值分別為a11、b11、c11、d11,則覆蓋了該業務場景功能點組合矩陣的一個元組4-T=(a11,b11,c11,d11),如果之前沒有被覆蓋過,該生產日志請求納入到測試用例庫中,為業務場景一的一個測試用例。以此類推,逐步篩選出符合業務場景一的所有功能點組合的生產日志請求,并納入到測試用例庫中。當業務場景一功能點組合矩陣的所有元組被完全覆蓋,則業務場景一的測試需求是測試完備的。同理,篩選出業務場景二的測試用例。該測試用例自動生成方法的目標是篩選出能夠覆蓋功能點組合的生產日志請求,使得所有業務場景的測試需求都是測試完備的。
本實驗以民航運價系統為例,使用生產日志和業務數據驗證本文所提測試用例精簡的效果和自動生成方法的可行性。
民航運價系統,每天處理約2 000萬筆交易,生成約120 G日志;包含3年的業務數據,近500 G。本實驗使用2022年1月29日交易日期的生產日志和2022年8月25日的業務數據。系統包含3年的業務數據,即2019年8月26日—2022年8月25日三年的全部數據內容。
以國航運價業務數據為樣本,共涉及323 897條樣本數據,10個功能點,功能點分別為:去程星期限制、回程星期限制、提前購票限制、運價組合限制、團隊人數限制、團隊拆分限制、缺口程組合限制、往返程組合限制、代碼共享限制、適用代碼共享承運人。對于該樣本數據,不劃分業務場景時,需要155 520個測試用例保證測試完備性。
根據標簽,可以將樣本數據劃分為207個業務場景,其中最多涉及7個功能點,最少涉及1個功能點,共需要4 421個測試用例保證測試完備性。經過精簡后,可以歸并為12個業務場景,其中最多涉及7個功能點,最少涉及2個功能點,共需要2 592個測試用例保證測試完備性。
以精簡后的某一業務場景“T/CA3C212619”為例,該業務場景涉及到3個功能點,分別為:
提前購票限制,取值集合為{[0天999天]、[1天999天]};
代碼共享限制,取值集合為{[0]、[1]};
適用代碼共享承運人,取值集合為{[]、[山航/]}。
該業務場景生成的功能點組合矩陣包含8個3維元組,如表4所示。

表4 業務場景“T/CA3C212619”功能點組合矩陣
某一生產日志請求執行結果如圖2所示:

圖2 生產日志請求結果
該日志請求的執行結果覆蓋了業務場景“T/CA3C212619”功能點組合矩陣的第3個元組,可以納入到測試用例庫中。
本文提出了一種測試用例精簡與自動生成方法。首先,測試用例精簡方法通過劃分業務場景降維,通過歸并業務場景減少功能點組合矩陣,解決了測試需求維度爆炸問題,實驗結果顯示,在保證測試完備性的前提下,有效地減少了測試用例的數量,使得基于路徑覆蓋的測試具有可行性。再次,測試用例自動生成方法使用生產日志和業務數據,自動分析軟件系統的請求以及結果,抓取測試用例,大大提升了測試用例的范圍,以及測試覆蓋率,并且業務數據和生產請求更加貼合用戶的真實業務場景,提升了測試的可靠性,避免了無效的測試。雖然本方法使用的打樁技術是侵入式的,但是可以采用組件掛載技術,通過配置動態開關,控制是否開啟打樁程序,對生產系統功能和性能無影響。綜上,本文所提方法在工程實踐中具有較大的應用價值。