有贊通用性接口健壯性掃描方案

圖片

作者:王興芹

部門:技術中心 / 業務技術

一、背景

1.1 業務背景

    隨着公司業務的快速發展,需求越來越多、迭代越來越快,在有限的測試人員和時間投入的前提下,如何做好質量防控,如何提高測試效率,是大家持續思考的問題。

    公司業務越來越複雜,應用越來越多,接口越來越多,接口的參數也越來越多,如何做好接口測試?如何做全接口的每一個參數的測試?

    在測試過程中,測試人員主要面臨以下問題:

    面對以上的問題,如果所有的測試都靠人工來完成,那將是很大的一筆人工和時間開銷。是否可以自動化構造測試數據來自動化部分測試類型,將是本文解決的問題。

1.2 本文解決的問題

    爲了解決上述問題,本文介紹了通用性接口健壯性掃描方案。本方案也爲質量保證、高效測試奠定了基礎。

     該方案重在忽略業務之間的差異,主要解決了以下問題:

二、系統設計

    測試的執行過程一般分爲三步:生成測試用例、測試用例執行、測試結果分析。通用性接口健壯性掃描主要圍繞這三個過程展開。主要分爲以下幾個核心流程:

    1. 數據源數據拉取及處理:該步驟基於各種平臺,比如網關、流量回放等,主要爲了獲取基線測試用例。
    1. 用例規則模型建立與用例生成算法制定:制定通用性用例規則模型,同時也擴展了自定義用戶規則模型,根據對應的算法,比如字段的 Empty 與非 Empty,字段的 NULL 與非 NULL,特殊值制定等比如字符型參數最長字符,數值型參數最大值、最小值以及通用性的特殊值等,生成用例數據。
    1. 用例執行:根據基線測試用例,會獲取到對應的服務、方法、測試環境。根據 2 的模型與算法,生成所有的用例數據,然後進行接口的調用及記錄執行結果。
    1. 結果分析:通用性接口健壯性掃描方案,對結果也是進行無業務邏輯的通用性的結果分析。這裏包括結果規則模型的確定與結果分析,剝離出有問題的測試用例結果並自動反饋。

    整體流程圖如下:

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) 後端執行結果異常

    問題背景:商家在使用我們的產品的時候,系統會出現不可預知的異常,這些異常都是代碼邏輯錯誤導致的。這類異常提示一般都有明顯的特徵,比如服務器錯誤、業務異常、遠程調用異常等。

    解決方案:爲了解決此類問題,抽取了幾千條結果數據,這些測試數據基本覆蓋了大部分的應用。爭對這些數據,找出這類錯誤的結果提示,制定成一個規則集合。滿足規則集合的則認爲是有問題的用例。

    這種規則的制定,需要採集各個應用的大量的結果數據,找出這類型錯誤的提示,加入到規則集合中。一旦拋出這種錯誤,我們就認定用例結果一定是異常的、不合理的。這種規則的集合,需要持續性的維護,並且需要制定好開發規範。後續開發遵循這種規範,不能隨手拈來一個錯誤提示。

三、總結與展望

    通篇介紹了通用性接口健壯性掃描的方案,基本能夠自動化解決部分接口通用性問題,整個過程無需人工干預,節省了不少人工成本,提高了應用的健壯性等。主要表現在:

    1. 自動化獲取基線用例
    1. 自動化生成用例數據,這個數據量更豐富,數據更完善,基本能夠覆蓋所有場景的接口參數數據,做到窮盡測試
    1. 自動執行用例,輸出結果
    1. 自動進行結果分析,判斷出有問題的用例
    1. 自動生成 jira,自動推送給開發修復
    1. 開發修復後可以人工點擊重試,既可驗證修復結果,無需重新構建用例,無需人工去調用。

     此方案忽略了業務之間的差異,掃描出的是通用性的邏輯問題。對於結果分析,還存在一定的弊端。比如期望結果是非 success 的,但是返回的結果卻是 success 的。這種還沒有確定的規則去挖掘出這類型的問題。因此,後續還有無限的提升空間。

後續可以朝着這幾個方向優化:

1)做到業務關聯性     目前是忽略了業務的差異性,但是還有很多和業務相關的通用問題,暫時還無解決方案。是否可以建立業務關聯性,來解決更多的問題。

2)結果精確性規則提煉     目前的規則制定,都是在有限的用例測試樣例數據上提煉出來的。制定完善的規則,需要更多的測試數據來分析。同時,也需要良好的開發規範來保障後續提示遵守這個規則。這兩者是相輔相成、相互促進、相互完善的。

3)解決 “返回 success 的接口實際上是錯的不符合預期的” 問題     返回 success 的接口實際上是錯的不符合預期的,目前這類問題還無法判斷。

4)基線用例持續性完善

    最初的基線用例數據可能只覆蓋了大部分的參數,但是並不能保證覆蓋到全部參數。因此基線用例的完善也是需要一個規則來持續性優化。

結合現在的設計,最終未來呈現出的方案會包括以下核心的流程:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ZqzjAr5ZAk-jz1Kts_Kh_w