nGrinder 參數使用


背景:

  性能測試中為了更加接近真實模擬現實應用,對於提交的信息每次都需要提交不同的數據,或使用不同的值,最為典型的就是登錄時的賬號。

  性能測試工具需要提供動態參數化功能,如商業化的LoadRunner就提供了非常強大的參數化支持,可支持各種參數取值方式,循環取值,或隨機取值

  而且還提供了參數模擬測試的功能,可以說非常完善

       c9111747-3048-4371-a170-fd53b752e045

    另外目前常用的性能測試工具Jmeter也提供了參數化的支持,如提供了"CSV Data Set Config"組件,可設置取值出的變量和取值結束后是否循環等

          f6dcfadb-2ef4-4521-85c4-ef947daa2b63

   在nGrinder中怎么設置參數呢,它並沒有提供現成的參數化工具,你無法直觀的設置參數取值方法,都只能在腳本中處理

   在開始之前我們需要更深刻得去理解測試場景中進程,線程等的概念

線程,進程,測試次數:

   在測試場景設置中,我們先簡單假設不根據時間測試,只根據次數來測試,那么在測試場景中,需要設置的參數就包括了

   進程數,線程數,測試數

   虛擬用戶數=進程數*線程數

   測試總數=虛擬用戶數*測試數

   就是說,如果進程數設置為5,線程數設置為2,那么虛擬用戶數為10

   如測試數設為3,那么一共運行的測試總次數為10*3=30

      b66b4c01-b1c5-4487-b16b-55ee933e307f

     再回想一下,之前Groovy腳本中的結構,BeforeThread,或者AfterThread,在幫助中的這幅圖,可以更清楚的說明整個過程,在圖中

     每個進程下有若干的線程,每個線程,執行若干次測試

         8aa659f9-049d-4cd6-b958-29f8742f2191

Groovy腳本獲取相關的值:

    在Groovy中,通過提供的方法可獲取包括當前的進程號,當前的線程號,總的進程數,總的線程數,當前的測試數,總測試數等信息

    如測試進程數設置為5,測試線程數設置為2,測試數為3

    在Groovy腳本中

    1 processnumber=grinder.processNumber  //獲取當前的進程號,應該會相應返回0,1,2,3,4

    2 totalprocess=grinder.getProperties().getInt("grinder.processes", 1) //獲取測試的進程總數,返回5

    3 threadnumber=grinder.threadNumber  //獲取當前的線程號,應該會相應返回0,1

    4 totalthread=grinder.getProperties().getInt("grinder.threads", 1) //獲取測試的線程總數,應該返回2

    5 run=grinder.runNumber;//獲取當前的測試號,應該相應返回1,2,3

    6 totalrun=grinder.getProperties().getInt("grinder.runs", 1); //返回測試的總數,如3

    因此現在在每個測試中,我們都可以明確獲取測試的進程,線程和測試數的相關信息

    當我們需要做參數化的時候,就可以根據這些信息來進行計算

    nGrinder中有線程,有進程,還有測試數的概念,所以計算參數的時候,其實比LoadRunner或Jmeter更復雜,Jmeter中只有線程的概念。

    當我們試圖要弄明白里面的這些概念時,要慢慢來,先嘗試着把設置弄簡單點,然后再逐步逐步設置的復雜,才更容易理解

 

    下面我們假設幾種場景來說明如何取值,假設把一份賬號存放在資源中,我們要取的參數就是這個賬號,可能需要循環取,可能需要不重復的取

腳本參數_循環取數,單進程,賬號資源冗余:

    設置的場景如下:  

          image

    這個場景中,我們簡單得把進程設置為1,這樣就只需要考慮多線程,然后測試次數設置為5,但線程數量小於資源賬號數

    假設資源中賬號為QAARKTESR_0001,QAARKTESR_0002.。。。QAARKTESR_0010

    我們預期的取值應該是:

           image

     在Groovy中,在一開始先就把文件讀取過來,然后轉換為字符數組

     def array = new File('./resources/accountlist.txt') as String[]

     那在每次測試的時候,只要使用當前的線程號,0,1,2就可以取得賬號

     為了簡單說明,在Groovy中,打印當前的線程,當前的測試次數,和取得的賬號

     grinder.logger.info("thread number, run, account {},{},{}",grinder.threadNumber,grinder.runNumber,array[grinder.threadNumber]);

             1d051682-828d-4054-8f18-a75d718307bc

      測試執行之后,查看日志輸出

           e93d18e9-ad69-4985-812b-dfcb02a25fb8[5]

     

      檢查日志,可以看到輸出符合我們的預期,線程從0到2,執行次數從0到4,取了三個賬號,每個執行了5次

腳本參數_循環取數,但進程,賬號資源缺乏

  還是剛才的場景,只是我們讓線程數大於資源數量

        image

   此時賬號只有了三個,QAARKTESR_0001,QAARKTESR_0002,QAARKTESR_0003

   這樣的時候,我們預期的參數取值應該是這樣,其中,賬號循環取值

         image

   仍然是把賬號讀取到數組中,我們仍然是通過線程的號去取數組中的賬號,但因為數組長度要小於線程數,所以此時需要用取余的操作

   int len=array.size();  //先取數組的長度,此時應該返回3

   int arrayindex=grinder.threadNumber%len;  //每次循環的賬號應該是等於線程數%長度

   grinder.logger.info("thread number, run, account {},{},{}",grinder.threadNumber,grinder.runNumber,array[arrayindex]);

   測試場景設置

          13982008-f456-4394-b78f-bf852626c057

     查看測試日志:

       38b7691a-e0f2-47c0-98e4-c292e09424db

     可以看到線程3,此時循環取得的賬號是賬號1 thread number, run, account 3,0,QAARKTESR_0001

     線程4 ,此時循環取的賬號是賬號2 ,thread number, run, account 4,0,QAARKTESR_0002

腳本參數_循環取數,多進程,賬號資源冗余

     剛才在1,2兩種場景中,我們都把進程設置為1,這樣我們就可以只考慮線程,但如果我們把進程也添加進來,那么如何循環取參數呢?

     一旦把進程考慮進來,就要比之前的要復制多了,我們還是先看比較簡單的情況

     此時我們假設,賬號的數要大於虛擬用戶的數

     賬號我們仍然是QAARKTESR_0001一直到QAARKTESR_0010

     場景設置如下:

             image

     那么我們預期的參數取值,應該是這樣的

         image

    那么這個時候,我們要取的賬號就需要進行一下簡單的計算

    序號=線程總數*當前的進程號+當前的線程號

    注意,所有的進程,線程,測試號都是從0開始

    如第一個進程,進程號就是0 ,線程總數是3

    那么每個線程中,計算的方法,就是0*3+0,1,2

   int threadcount=grinder.getProperties().getInt("grinder.threads", 1);  //取線程總數,因為是3

   int arrayindex=grinder.processNumber*threadcount+grinder.threadNumber;          

   grinder.logger.info("thread number, run, account {},{},{}",grinder.threadNumber,grinder.runNumber,array[arrayindex]);

   場景設置:

          a1313b6b-c454-4878-b735-042c636a24a7

      運行之后查看日志,可以發現因為收到日志的限制,直接可以查看的只是一個進程的日志,另外一個進程的日志沒辦法查看到

      本身日志顯示或查看的限制,所以只能看到線程1,2,3各自取了賬號QAARKTESR_0001,QAARKTESR_0002,QAARKTESR_0003

      思考:

      如果本身是多進程,多線程,那么如果賬號數量還小於總的線程數,那么如何計算呢

      其實公式和剛才的公式是一樣的,只是在最后取余一下賬號總數

      即序號=( 進程號*線程總數+線程號)%賬號總數

腳本參數_保證參數唯一性:

    有時候我們需要在循環取參數的時候保證每個參數都是唯一取一次,比如注冊賬號,第二重復注冊可能就已經是失敗了

    那么這時,我們需要每次測試的時候都需取唯一的數據

    我們還是先設置進程數量為1,此時仍然只需要考慮線程數    

         image

   那么這個時候,其實測試次數其實是9,而我們准備的賬號總數是10,所以是充分的,准備正好的9個賬號也是可以的,應該不會影響最后的取值

   按照這樣的設置,我們預期的結果應該是這樣的

        image

   那么如何計算得出這樣的參數呢

   取賬號序號=(當前線程號*循環測試總數)+當前的測試數序號

   如當前線程號是1,循環測試總數固定是3 ,當前測試序號是1

   那么應該取的序號是   1*3+1=4

   groovy中的腳本應該

   int testcount=grinder.getProperties().getInt("grinder.runs", 1);  //測試總數,應該為3

   int arrayindex=(grinder.threadNumber*testcount)+grinder.runNumber;// 取在數組中的序號                 

   grinder.logger.info("thread number, run, account {},{},{}",grinder.threadNumber,grinder.runNumber,array[arrayindex]);

實際設置場景

       07349464-bf75-4546-b7af-25a6fc947ac7

   運行,然后查看日志,可以看到實際循環了9個賬號,和我們的預期是一樣的

         881c2eb7-906f-49f9-a773-c1dd237f97a8

   這個方式其實相當於LoanRunner中參數設置中取值方式為Unique的方式,但通過這種方式計算的時候,因為本身是要保證數據不重復,所以測試循環次數,還有數據要自己計算好,日常工作中常常遇到的是不重復的循環注冊賬號的場景

   但這個場景中,我們還是簡單的把進程數設置為了1,只考慮多線程

   如果循環取數,同樣是多線程的時候,怎么計算出這個序號呢

   其實思路是一樣的,只是公式看上去要復雜一點點

   序號=(進程數*線程總數*測試總數)+(線程數*測試總數)+當前的測試序號

   只要明白了nGrinder中的進程,線程,循環測試的概念,並且我們本身都是可以從方法中取得這些數據,所以不論多進程,多線程,還是單進程,單線程都是一樣的,都是可以計算出來的

參考資料:

  1  http://debugtalk.com/post/head-first-locust-advanced-script/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM