有贊通用性接口健壯性掃描方案
作者:王興芹
部門:技術中心 / 業務技術
一、背景
1.1 業務背景
隨着公司業務的快速發展,需求越來越多、迭代越來越快,在有限的測試人員和時間投入的前提下,如何做好質量防控,如何提高測試效率,是大家持續思考的問題。
公司業務越來越複雜,應用越來越多,接口越來越多,接口的參數也越來越多,如何做好接口測試?如何做全接口的每一個參數的測試?
在測試過程中,測試人員主要面臨以下問題:
-
測試人員都把精力放在覈心的業務測試上。很少騰出時間來關注接口的各種參數類型的測試。
-
接口越來越多、接口參數也越來越多,很難做到每個接口、每個參數的窮盡測試。
-
針對接口參數設計的測試用例,用例數量通常都很多,如果只靠人工投入,會大大增加測試人員的時間成本,降低測試效率。
-
測試人員核心關注點在正常的業務數據上,非正常業務數據相關的邏輯很少考慮周全,比如最大值、最長字符、特殊值等。
面對以上的問題,如果所有的測試都靠人工來完成,那將是很大的一筆人工和時間開銷。是否可以自動化構造測試數據來自動化部分測試類型,將是本文解決的問題。
1.2 本文解決的問題
爲了解決上述問題,本文介紹了通用性接口健壯性掃描方案。本方案也爲質量保證、高效測試奠定了基礎。
該方案重在忽略業務之間的差異,主要解決了以下問題:
-
建立通用的規則來生成測試用例
-
解決通用性接口測試問題,比如邊界值、最大值等
-
全自動化生成、執行測試用例,整個過程無需人工參與,節約成本
-
根據特定的產品規則,解決產品上的共性問題
二、系統設計
測試的執行過程一般分爲三步:生成測試用例、測試用例執行、測試結果分析。通用性接口健壯性掃描主要圍繞這三個過程展開。主要分爲以下幾個核心流程:
-
- 數據源數據拉取及處理:該步驟基於各種平臺,比如網關、流量回放等,主要爲了獲取基線測試用例。
-
- 用例規則模型建立與用例生成算法制定:制定通用性用例規則模型,同時也擴展了自定義用戶規則模型,根據對應的算法,比如字段的 Empty 與非 Empty,字段的 NULL 與非 NULL,特殊值制定等比如字符型參數最長字符,數值型參數最大值、最小值以及通用性的特殊值等,生成用例數據。
-
- 用例執行:根據基線測試用例,會獲取到對應的服務、方法、測試環境。根據 2 的模型與算法,生成所有的用例數據,然後進行接口的調用及記錄執行結果。
-
- 結果分析:通用性接口健壯性掃描方案,對結果也是進行無業務邏輯的通用性的結果分析。這裏包括結果規則模型的確定與結果分析,剝離出有問題的測試用例結果並自動反饋。
整體流程圖如下:
2.1 數據源解析
整個設計的基礎是基於基線測試用例。爲了獲取基線測試用例數據,需要建立數據源拉取策略。數據源來源於以下平臺:網關平臺、流量回放平臺等。
網關層數據的數量巨大,如果拉取數據量過多,會導致拉取時間過長,很容易失敗。同時如果多個應用或者多個線程同時拉取,很容易出現併發問題導致數據源拉取失敗。
爲了避免大量的無效數據源數據拉取,首先建立數據源數據拉取策略,爭對性的拉取數據。同時爲了避免數據量過多而導致拉取數據失敗,設置了每 30min 拉取一次數據,如果本次拉取失敗,則任務重試 N 次,成功則停止拉取,N 次失敗後在不在拉取。
獲取數據源後,即可對數據源進行解析。通過數據源數據,解析出對應的應用、服務、參數類型、接口參數等,通過接口參數來獲取基線用例數據。因爲整個公司的應用很多,所以,根據配置策略,只解析在系統裏配置過的應用數據,過濾掉沒有配置過的應用的數據。下面是整個數據源的拉取與解析流程圖。
網關平臺的數據源只包含網關層的信息,並不能獲取到後端的服務信息。我們的調用是基於 dubbo 服務的調用,所以還需要通過有贊網關平臺,查詢並獲取到對應的 dubbo 服務的名稱、方法、參數類型、返回值類型等信息。然後根據網關的參數,組裝成 dubbo 服務的接口參數,最後把這些數據進行持久化存儲。
爲了豐富基礎用例數據,後續會接入多種平臺,獲取更多的數據源數據。
2.2 用例數據生成算法模型
本篇文章的核心在於建立通用性用例數據生成的算法模型。核心流程如下:
首先建立基本的算法模型,主要包括基本的規則以及按照規則生成用例數據的算法。同時還擴展了用戶自定義規則,根據用戶自定義規則來生成對應的用例數據。
下面簡單舉例 NULL 規則生成的數據用例過程:
比如
class ParentObject{
Integer paattr1;
String paattr2;
SubObject paattr3;
}
class SubObject{
Integer sbattr1;
String sbattr2;
}
public RetType testMethod(ParentObject parentObject){}
上述方法的基線用例爲:
{
"paattr1":3,
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr1":100,
"sbattr2":"subobjectnullcases"
}
}
根據NULL規則,會生成如下的測試用例:
用例1:
{
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr1":100,
"sbattr2":"subobjectnullcases"
}
}
用例2:
{
"paattr1":3,
"paattr3":{
"sbattr1":100,
"sbattr2":"subobjectnullcases"
}
}
用例3:
{
"paattr1":3,
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr2":"subobjectnullcases"
}
}
用例4:
{
"paattr1":3,
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr1":100
}
}
上述的 NULL 規則用例生成具有很好的通用性。EMPTY 規則生成和 NULL 類似。特殊值類型的規則制定,尤其是特殊值的制定,除了使用通用性的數據規則之外,如 Double.MAX_VALUE,Integer.MAX_VALUE 等,還可以使用業務上的通用性特殊數據。具體如何制定特殊值,需要根據業務來分析。
特殊值規則制定好之後,則根據參數類型,用指定的特殊值去替換,生成對應的測試用例。假設這裏指定如下特殊值:Integer.MAX_VALUE 與 String.maxLength("AAA.........")。最後生成的用例如下:
用例1:
{
"paattr1":Integer.MAX_VALUE,
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr1":100,
"sbattr2":"subobjectnullcases"
}
}
用例2:
{
"paattr1":3,
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr1":Integer.MAX_VALUE,
"sbattr2":"subobjectnullcases"
}
}
用例3:
{
"paattr1":3,
"paattr2":"String.maxLength("AAA.........")",
"paattr3":{
"sbattr1":100,
"sbattr2":"subobjectnullcases"
}
}
用例4:
{
"paattr1":3,
"paattr2":"parentobjectnullcases",
"paattr3":{
"sbattr1":100,
"sbattr2":"String.maxLength("AAA.........")"
}
}
上述兩種都是通用的規則算法,實際應用中遠不止這些,有很多需要根據業務規則來確定規則模型。自定義算法模型就是根據用戶自定義規則來生成對應的數據用例,增加了模型建立的靈活性。每個模型都有各自對應的生成算法,每個模型需要實現 generateCases 方法即可。總的獲取所有模型用例算法流程如下:
public List<Cases> caseGenerate(){
for(AlgorithmModel algorithmModel: algorithmModels){
baseCase = getBaseCase();
caseTmpList = algorithmModel.generateCases();
cases.addALl(caseTmpList);
}
return cases;
}
2.3 用例執行
數據用例生成後,即可進行用例的執行。爲了和數據源拉取任務錯開,也是每隔 30MIN 執行一次,但是執行的時間段數據比日誌拉取的時間早 30min。比如數據源拉取時間爲當前時間的前 30min,則用例執行的時間爲當前時間的前 60Min。主要是爲了避開數據源拉取任務的數據還沒拉完,導致用例漏執行。具體執行流程如下:
根據算法模型生成的用例數據量一般都比較大,爲了加速執行過程,採用多任務執行。服務調用可能會出現失敗情況,如果失敗,則根據補償機制來重試,最終確保每個數據用例都能執行完成。補償機制過程如下:
2.4 結果分析
通篇最難的是如何進行結果分析,即如何判斷執行的結果是有問題的。主要有兩種情況:1)返回 success 的接口實際上是錯的不符合預期的;2)返回非 success 的接口實際上是正確的符合預期的。所以結果判斷規則的制定特別重要,直接關係到結果判斷的準確性,即整個方案的可行性。
目前爭對方案能解決的問題,主要制定兩種類型的錯誤提煉規則:一、判斷錯誤提示不合理;二、判斷後端執行結果不合理。
1) 錯誤提示不合理
問題背景:商家在使用我們的產品的時候,會報一些錯誤。但是有些錯誤,商家會看不懂,不明白其中的意思,比如下圖的錯誤提示。
解決方案:爲了解決此類問題,展示給商家的更友好的錯誤提示,提煉了錯誤提示不合理的規則,自動判斷接口返回結果不符合規則的用例。
這種規則的前提是基於接口返回的結果是非 success。如何確定呈現給商家的錯誤提示不合理,需要測試、開發、產品人員一起確定出來 “什麼樣的提示規則是合理的、商家易理解的”。比如呈現給商家的錯誤提示遵循一定的格式,呈現給商家的錯誤文案裏一定不能包括專業性的詞彙、不能包括一連串的英文、數字、不能包括傳參對象的屬性名稱,呈現給商家的錯誤提示文案必須是完整的一個句子等等。根據這些規則,制定代碼提煉錯誤的規則,即可準確判斷出接口錯誤提示是否合理。
2) 後端執行結果異常
問題背景:商家在使用我們的產品的時候,系統會出現不可預知的異常,這些異常都是代碼邏輯錯誤導致的。這類異常提示一般都有明顯的特徵,比如服務器錯誤、業務異常、遠程調用異常等。
解決方案:爲了解決此類問題,抽取了幾千條結果數據,這些測試數據基本覆蓋了大部分的應用。爭對這些數據,找出這類錯誤的結果提示,制定成一個規則集合。滿足規則集合的則認爲是有問題的用例。
這種規則的制定,需要採集各個應用的大量的結果數據,找出這類型錯誤的提示,加入到規則集合中。一旦拋出這種錯誤,我們就認定用例結果一定是異常的、不合理的。這種規則的集合,需要持續性的維護,並且需要制定好開發規範。後續開發遵循這種規範,不能隨手拈來一個錯誤提示。
三、總結與展望
通篇介紹了通用性接口健壯性掃描的方案,基本能夠自動化解決部分接口通用性問題,整個過程無需人工干預,節省了不少人工成本,提高了應用的健壯性等。主要表現在:
-
- 自動化獲取基線用例
-
- 自動化生成用例數據,這個數據量更豐富,數據更完善,基本能夠覆蓋所有場景的接口參數數據,做到窮盡測試
-
- 自動執行用例,輸出結果
-
- 自動進行結果分析,判斷出有問題的用例
-
- 自動生成 jira,自動推送給開發修復
-
- 開發修復後可以人工點擊重試,既可驗證修復結果,無需重新構建用例,無需人工去調用。
此方案忽略了業務之間的差異,掃描出的是通用性的邏輯問題。對於結果分析,還存在一定的弊端。比如期望結果是非 success 的,但是返回的結果卻是 success 的。這種還沒有確定的規則去挖掘出這類型的問題。因此,後續還有無限的提升空間。
後續可以朝着這幾個方向優化:
1)做到業務關聯性 目前是忽略了業務的差異性,但是還有很多和業務相關的通用問題,暫時還無解決方案。是否可以建立業務關聯性,來解決更多的問題。
2)結果精確性規則提煉 目前的規則制定,都是在有限的用例測試樣例數據上提煉出來的。制定完善的規則,需要更多的測試數據來分析。同時,也需要良好的開發規範來保障後續提示遵守這個規則。這兩者是相輔相成、相互促進、相互完善的。
3)解決 “返回 success 的接口實際上是錯的不符合預期的” 問題 返回 success 的接口實際上是錯的不符合預期的,目前這類問題還無法判斷。
4)基線用例持續性完善
最初的基線用例數據可能只覆蓋了大部分的參數,但是並不能保證覆蓋到全部參數。因此基線用例的完善也是需要一個規則來持續性優化。
結合現在的設計,最終未來呈現出的方案會包括以下核心的流程:
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ZqzjAr5ZAk-jz1Kts_Kh_w