成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

自動化接口用例從 1 到 1000 過程中的實踐和思考

lmxdawn / 1660人閱讀

摘要:在本文中,和大家探論下如何編寫大量自動化接口用例以及保持結(jié)果穩(wěn)定。如通過特定名字的變量名和數(shù)據(jù)進行關(guān)聯(lián)。如果執(zhí)行過程需要依賴其他系統(tǒng)的接口的話,那么其他系統(tǒng)發(fā)生了變更或故障就會影響自身用例的進行。使用不同賬號等進行隔離。

引言

當(dāng)一個新人剛加入公司的時候,我們通常告訴新人怎么去寫一個自動化用例:從工程配置到如何添加接口、如何使用斷言,最后到如何將一個用例運行起來。

而在實際工作和業(yè)務(wù)場景中,我們常常面臨著需要編寫和組織一堆用例的情況:我們需要編寫一個業(yè)務(wù)下的一系列的自動化接口用例,再把用例放到持續(xù)集成中不斷運行。面臨的問題比單純讓一個用例運行起來復(fù)雜的多。

本人加入有贊不到一年,從寫下第 1 個 case 開始,持續(xù)編寫和運行了 1000 多個 case ,在這過程中有了一些思考。在本文中,和大家探論下如何編寫大量自動化接口用例以及保持結(jié)果穩(wěn)定。

一、執(zhí)行效率

目前使用的測試框架是基于 spring ,被測接口是 dubbo 的服務(wù)。 dubbo 的架構(gòu)如圖(源自官網(wǎng))

服務(wù)使用方的初始化需要經(jīng)歷以下這幾個步驟:

監(jiān)聽注冊中心

連接服務(wù)提供端

創(chuàng)建消費端服務(wù)代理

本地調(diào)試用例時,發(fā)現(xiàn)速度非常慢,運行一個用例需要 30s,而實際執(zhí)行用例邏輯的時間大概在 1s 左右,主要時耗在服務(wù)消費者的初始化階段。

測試工程中,各服務(wù)的 test 類繼承了同一個基類,基類里面做了各服務(wù)的初始化的步驟。在對接的服務(wù)數(shù)目較少時,需要初始化的對象較少,對用例運行的影響并不大,但隨著業(yè)務(wù)的增多,服務(wù)數(shù)目也增多,導(dǎo)致跑 A 服務(wù)接口的用例時把大量未用到的 B 服務(wù)、C 服務(wù)也一起初始化了,導(dǎo)致整體時耗大大增加。

解決辦法:在運行用例時只初始化需要的服務(wù)使用方,減少不必要的初始化開銷。

二、用例編寫和維護 一個用例示例

以一個簡單的業(yè)務(wù)場景為例:商家可以在后臺創(chuàng)建會員卡給店鋪的會員領(lǐng)取,商家可以對會員卡進行更新操作,這里需要有一個自動化用例去覆蓋這個場景。

用例編寫的基本步驟為:

step 1 :準(zhǔn)備數(shù)據(jù)構(gòu)造新建會員卡和更新會員卡的對象

step 2 :執(zhí)行創(chuàng)建會員卡

step 3 :執(zhí)行更新會員卡

step 4 :檢查更新結(jié)果

step 5 :清理創(chuàng)建的會員卡

轉(zhuǎn)換成代碼為:

    @Test
    public void testUpdate() {
        try {
            /*
             * 創(chuàng)建新建和更新的卡對象
             */
            CardCreateDescriptionDTO descCreate = new CardCreateDescriptionDTO();
            descCreate.setName(xxxx);
            //此處省略若干參數(shù)設(shè)置過程....
            
            CardUpdateDescriptionDTO descUpdate = new CardUpdateDescriptionDTO();
            descUpdate.setName(xxxxx);
            //此處省略若干參數(shù)設(shè)置過程....
            /*
             * 新建會員卡
             */
            cardAlias = cardService.create((int) kdtId, descCreate,operator).getCardAlias();
             /*
             * 更新會員卡
             */
            cardService.update(kdtId, cardAlias, descUpdate, operator);
            /*
             * 校驗編輯是否生效
             */
            CardDTO cardDTO = cardService.getByCardAlias(cardAlias);
            Assert.assertEquals(cardDTO.getName(), xxxx, "會員卡更新失敗");
            //此處省略若干參數(shù)校驗過程....
        } catch (Exception e) {
            Assert.assertNull(e);
        } finally {
            try {
                if(cardAlias!=null) {
                    cardService.deleteByCardAlias((int) kdtId, cardAlias, operator);
                }
            } catch (Exception e) {
                Assert.assertNull(e, e.getMessage());
            }
        }
    }

按照預(yù)期的步驟去寫這個 case ,可以滿足要求,但是如果需要擴展一下,編寫諸如:更新某種類型的會員卡、只更新會員卡的有效期這樣用例的時候,就會覺得按這個模式寫 case 實在太長太啰嗦了,痛點在以下幾個地方:

數(shù)據(jù)準(zhǔn)備比較麻煩,需要逐一設(shè)值

數(shù)據(jù)檢查部分逐字段檢查,心好累

每個創(chuàng)建相關(guān)的用例都需要清理資源,每次都需要做一次,太重復(fù)了

用例本身關(guān)注的是更新這個操作,卻花了太多時間和精力在其他地方,很多是重復(fù)勞動。代碼編寫里有一個重要原則,DRY(Don"t Repeat Yourself),即所有重復(fù)的地方都可以考慮抽象提煉出來。

三段式用例

可以將大部分用例的執(zhí)行過程簡化為三個部分:

數(shù)據(jù)準(zhǔn)備

執(zhí)行操作

結(jié)果檢查

用簡單的三個部分來完成上述用例的改寫:

數(shù)據(jù)準(zhǔn)備

    @DataProvider(name="dataTestUpdate")
    public Object[][] dataTestUpdate() {
        return new Object[][]{    
{cardFactory.genRuleNoCreate(...),cardFactory.genRuleNoUpdate(...)},
{cardFactory.genRuleCreate(...),cardFactory.genRuleUpdate(...)},
{cardFactory.genPayCreate(...),cardFactory.genPayUpdate(...)}
       };

    }

執(zhí)行操作+結(jié)果檢查

Test(dataProvider = "dataTestUpdate")                 
   public void testUpdate(CardCreateDescriptionDTO desc,CardUpdateDescriptionDTO updateDesc){                        
       try {    
           /*
           * 執(zhí)行操作:創(chuàng)建+更新
           */                            
           //創(chuàng)建會員卡                                                     
           CardDTO cardBaseDTO = createCard(kdtId,desc,operatorDTO);        
           cardAlias=cardBaseDTO.getCardAlias();                                          
           recycleCardAlias.add(cardAlias); //將卡的標(biāo)識放入垃圾桶后續(xù)進行回收                                                    
           CardDTO ori = getCard(kdtId,cardAlias);     
          //更新會員卡                            
          updateCard(kdtId,cardAlias,updateDesc,operatorDTO);                                                                                            
           CardDTO updated = getCard(kdtId,cardAlias);    
           /*
           * 結(jié)果檢查
           */                          
      checkUpdateCardResult(ori,updated,updateDesc,kdtId);                                               
                                                                                                 
       } catch (Exception e) {                                                                   
           Assert.assertNull(e);                                                                 
       }                                                                                         
                                                                                                 

其中可行的優(yōu)化點將在下面娓娓道來。

測試數(shù)據(jù)的優(yōu)化

在這個用例中,數(shù)據(jù)準(zhǔn)備的部分使用了 dataProvider 來復(fù)用執(zhí)行過程,這樣不同參數(shù)但同一過程的數(shù)據(jù)可以放在一個 case 里進行執(zhí)行和維護。

數(shù)據(jù)生成使用了工廠方法 CardFactory ,好處是簡化了參數(shù),避免了大量 set 操作(本身包裝的就是 set 方法);另一方面,根據(jù)實際的業(yè)務(wù)場景,可以考慮提供多個粒度的構(gòu)造方法,比如以下兩個構(gòu)造方法需要提供的參數(shù)差別很大:

第一個主要用在驗證創(chuàng)建接口的場景,檢查各個傳入的參數(shù)是否生效。

    public CardCreateDescriptionDTO genRuleCreate(Boolean isPost,Integer discount,Long rate,Long pointsDef,
                        String couponIds, Long num, Long growth,Long termToCardId,Long amount,Long points,Long trade){

第二個用在如刪除的場景,所以只需要一個創(chuàng)建好的會員卡對象,并不是很關(guān)注創(chuàng)建的內(nèi)容是什么。

    public CardCreateDescriptionDTO genRuleSimpleCreate(String name){

在上面的優(yōu)化過的用例中,能夠執(zhí)行更新操作的前置條件是需要有一個已經(jīng)創(chuàng)建的會員卡,在實際用例編寫的時候通過直接創(chuàng)建一個會員卡,然后執(zhí)行更新完成后再回收刪除這張會員卡來滿足這個條件。另一種提供滿足操作所需前置數(shù)據(jù)的方式是預(yù)置數(shù)據(jù)(預(yù)先生成數(shù)據(jù))。

以下情況可以考慮預(yù)置數(shù)據(jù)的方式:

提高用例穩(wěn)定性,解依賴,加快執(zhí)行速度

需要對特定的類型、狀態(tài)的對象進行查詢

創(chuàng)建或者構(gòu)造比較麻煩

典型的場景:比如編寫查詢的用例時預(yù)先創(chuàng)建滿足條件的對象供查詢用例使用。

談到預(yù)置數(shù)據(jù),不得不談的一個問題是數(shù)據(jù)管理。在編寫用例的時候,"我們往往需要一個____的資源",框框里面的即是對數(shù)據(jù)的描述和要求,比如我需要一個全新的賬號,一個支付過的訂單號,一張免費的會員卡,來完成我們的用例。所以需要對數(shù)據(jù)進行標(biāo)記而不是簡單硬編碼的方式在用例中使用。

如:通過特定名字的變量名和數(shù)據(jù)進行關(guān)聯(lián)。

    /**只做查詢卡,不做領(lǐng)卡刪卡*/
    public Long queryCardUid = DataMocker.MOCK_YZUID.get(1);
    /**用戶卡類操作,領(lǐng)卡刪卡*/
    public Long takeCardUid = DataMocker.MOCK_YZUID.get(6);
    /**退款用*/
    public Long refundCardUid =DataMocker.MOCK_YZUID.get(4);
 

對數(shù)據(jù)進行標(biāo)記后,會發(fā)現(xiàn)有一部分?jǐn)?shù)據(jù)是用來驗證寫操作(如創(chuàng)建、更新),有一部分?jǐn)?shù)據(jù)是查詢使用。如果數(shù)據(jù)又要被寫操作的 case 使用,又要被讀操作的 case 使用,那么寫操作的問題和異常就會影響讀操作 case 的執(zhí)行結(jié)果。所以,在代碼工程中,可以進行約定,將讀寫用到的資源進行分離來降低數(shù)據(jù)的耦合:

查詢 case 用的賬號不做更改對象的操作

查詢 case 用的對象不做修改、刪除的操作

驗證增、刪、改行為的資源使用特定賬號,且資源最后做回收刪除處理(因為資源總數(shù)有限)

最后,用例執(zhí)行完成后需要清理資源。這里的清理資源采用的是一個全局的 list 的方式保存需要清理的資源信息,在用例執(zhí)行過程中往里增加數(shù)據(jù):(recycleCardAlias.add(cardBaseDTO.getCardAlias());),
然后用對應(yīng)的方法取其中的數(shù)據(jù)進行刪除,類似垃圾桶。與原有執(zhí)行完就執(zhí)行清理動作相比,使用垃圾桶更加靈活,可以選擇控制下清理頻率。

比如每次在 AfterMethodAfterClass 中去清理。

    //統(tǒng)一回收
    @AfterMethod
    public void tearDownMethod() {

        for(int i =0;i
對方法的適度封裝

在實際編寫用例的時候,有兩個地方可以考慮進行方法封裝,從來簡化調(diào)用,方便維護:

封裝基本操作。如果刪除操作依賴創(chuàng)建操作,查詢操作依賴創(chuàng)建操作,那么創(chuàng)建操作可以看作是個基本操作,可以對創(chuàng)建操作包裝一下,將注意力關(guān)注于實際需要執(zhí)行和驗證的地方??梢苑庋b的東西很多,有參數(shù)封裝、異常處理的封裝、一些輪訓(xùn)、重新邏輯的封裝。createCard()getCard()、deleteCard方法就是將接口、參數(shù)組裝、檢查等封裝好的方法。

封裝檢查方法。上述用例中的檢查采用了一個檢查方法代替了以往的多個assert:
checkUpdateCardResult(ori,updated,updateDesc,kdtId); ,在方法里包裝了一些關(guān)鍵字段的比較,包括兩個對象之間成員是否一致的比較。所有的更新操作的結(jié)果都需要滿足:有變更的字段值變成新的值,未發(fā)生變更的值和原有一致。該方法實現(xiàn)了這種檢查邏輯,所以寫更新操作用例的同學(xué)不需要關(guān)注如何校驗,而是關(guān)心如何更新,因為檢查邏輯是現(xiàn)成的、通用的。將來檢查邏輯發(fā)生變更,也只需要維護這一個方法即可。

穩(wěn)定性

當(dāng)大批量用例進行運行時,用例集的失敗率會變得較高,幾個微小的瑕疵都會造成用例的失敗,此時我們需要更加關(guān)注用例的穩(wěn)定性。一些實踐中比較好的措施和方式:

減少外部依賴。如果執(zhí)行過程需要依賴其他系統(tǒng)的接口的話,那么其他系統(tǒng)發(fā)生了變更或故障就會影響自身用例的進行??梢钥紤]通過預(yù)先生成的數(shù)據(jù)來替代調(diào)用外部接口生成數(shù)據(jù)在用例中使用。

預(yù)置數(shù)據(jù)代替創(chuàng)建過程。由于操作越多穩(wěn)定性越低,使用預(yù)置數(shù)據(jù)而不是實時生成它,速度更快,穩(wěn)定性更高。

使用不同賬號等進行隔離。通過隔離,用例執(zhí)行失敗的臟數(shù)據(jù)就不會影響其他用例。

調(diào)優(yōu):超時、等待時間。線上超時時間設(shè)置的比較短,測試環(huán)境的機器配置不如線上,需要適時調(diào)大超時和等待時間來保證接口調(diào)用不會超時。

防御式編程。編寫測試代碼時不能假設(shè)數(shù)據(jù)已存在或者沒有臟數(shù)據(jù)殘留,所以預(yù)先的判斷和清理很重要,比如檢查到數(shù)據(jù)缺失就實時修復(fù)、用例運行之前考慮清除臨時數(shù)據(jù)。

定位并解決不穩(wěn)定的問題。有時候偶現(xiàn)用例失敗,可以考慮給被測應(yīng)用增加日志,同時持續(xù)多次運行用例多次(如 testNg 里增加threadPoolSize=1, invocationCount=50)來復(fù)現(xiàn)問題,最終解決問題。

總結(jié)

對于大規(guī)模用例的編寫、組織和運行的問題,文中從三個方面給出了有贊測試的實踐和思考:精簡初始化來提高執(zhí)行速度、優(yōu)化用例編寫降低編寫和維護成本、多種方式提高用例穩(wěn)定性,希望能給大家一些啟發(fā)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94713.html

相關(guān)文章

  • Web UI動化最佳實踐

    摘要:三思而后行自動化測試最終目的是啥投入產(chǎn)出比的最佳平衡點在哪很多實施者在搭建自動化框架前往往缺乏思考,為了自動化而自動化。 三思而后行 UI自動化測試最終目的是啥?投入產(chǎn)出比的最佳平衡點在哪?很多實施者在搭建UI自動化框架前往往缺乏思考,為了自動化而自動化。三思而后行,方向決定成敗。由于項目接口(API and Service)自動化代碼行覆蓋率已經(jīng)達到70%,基于當(dāng)前自動化人力和項目質(zhì)...

    canger 評論0 收藏0
  • 動化測試 之 “好用例、壞用例

    摘要:反之,好用例則是表現(xiàn)穩(wěn)定的用例。可以建立測試或開發(fā)人員壞用例檔案,并自動追蹤每一個壞用例的來源,督促負(fù)責(zé)人跟進解決。接下來,需要做的就是大家共同維護好這樣一個最佳狀態(tài),避免破窗理論的發(fā)生。 摘要: 自動化測試的重要性顯而易見,但自動化測試又無法解決所有問題,所以說完全依賴自動化是不可能的,但完全沒有自動化是萬萬不能。在軟件開發(fā)項目中,重度依賴人力進行持續(xù)回歸是一件非??菰锏闹貜?fù)工作。企...

    hot_pot_Leo 評論0 收藏0
  • 面試官:了解Fuzzing Test嗎?

    摘要:產(chǎn)生的崩潰測試用例可能難以分析,因為模糊測試的行為并不能告訴你關(guān)于軟件內(nèi)部運行方式的知識。模糊測試向軟件系統(tǒng)提供隨機輸入。 軟件質(zhì)量保障 專注測試圈,自動化測試、測試平臺開發(fā)、測試新技術(shù)、大廠測試崗面經(jīng)分享, 可以幫忙內(nèi)推BATJ等大廠!歡迎加VX溝通交流: ISTE1024 測試同...

    shusen 評論0 收藏0
  • 有贊 WEB-UI 動化實踐

    摘要:概述是由有贊開發(fā)的自動化工具,并以此實現(xiàn)了端和端的核心業(yè)務(wù)的自動化。旨在簡化開源工具提供的接口,方便自動化測試用例的設(shè)計。元素定位自動化用例其實可以分成兩部分,定位元素調(diào)用接口操作該元素。一臺用于跑自動化用例的服務(wù)器。 概述 Bee 是由有贊 QA 開發(fā)的 UI 自動化工具,并以此實現(xiàn)了 web 端和 wap 端的核心業(yè)務(wù)的自動化。旨在簡化開源工具提供的接口,方便 UI 自動化測試用例...

    h9911 評論0 收藏0
  • 隨行付微服務(wù)測試之單元測試

    摘要:輸出結(jié)果需要人工檢查的測試不是一個好的單元測試。為了有效的進行單元測試,需要遵循一定的方法,通常采用路徑覆蓋法設(shè)計單元測試用例。 在微服務(wù)架構(gòu)下高覆蓋率的單元測試是保障代碼質(zhì)量的第一道也是最重要的關(guān)口,應(yīng)該持之以恒。 背景 單元測試為代碼質(zhì)量保駕護航,是提高業(yè)務(wù)質(zhì)量的最直接手段,實踐證明,非常多的缺陷完全可以通過單元測試來發(fā)現(xiàn),測試金字塔提出者Martin Fowler 強調(diào)如果一個高...

    xiguadada 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<