1. 程式人生 > >LoadRunner腳本編寫

LoadRunner腳本編寫

開發環境 自動變 退出 ... 分支 close 不能 art .com

(一)

  性能測試工程師要懂代碼麽?答案是必須的。好多測試員認為在loadrunner中編寫腳本很難很牛X ,主要是大多測試人員並未做過開發工作,大學的那點程序基礎也忘記的差不多了。還有非計算機專業出身的測試員,所以對代碼望都比較望而生畏。

  好多人認為loadrunner只支持C語言(包括我之前也一直這麽認為),因為loadrunner默認的腳本是C語言的,其實它支持目前所有主流的語言,如:Java User、VB User、VB script User 、Javascript User、Mmicrosoft .NET等,總有一款適合你的吧,最起碼C語言是必修課吧。

對於編寫loadrunner腳本的態度

  現在有一輛自行車放在你的面前,你為顯示自己體力很好,每天走路去上班。我騎車只要半小時,而你走路卻要2小時,我們的目的是一樣的,你是為了讓人說你牛呢,還是讓人說你傻呢?當然自行車不是萬能的,比如,上班的地點在山上,自行車跟本上不去,自然走路就是唯一的選擇了。

  所以,對於loadrunner腳本,能錄制的部分就錄制改,不能錄制的就手寫,但前提是我們要會寫腳本。

認識loadrunner腳本                           

  Loadrunner自帶了一個小飛機訂票系統

技術分享圖片

  我們先啟動 Start Web server 服務,如果啟動成功,桌面右下角會有一個綠色的X ,然後打開瀏覽器訪問

http://127.0.0.1:1080/WebTours/  下面是我們loadrunner錄制一個登錄過程。

技術分享圖片
Action()
{
    
    web_url("WebTours", 
        "URL=http://127.0.0.1:1080/WebTours/", 
        "Resource=0", 
        "RecContentType=text/html", 
        "Referer=", 
        "Snapshot=t1.inf", 
        "Mode=HTML", 
        LAST);

    lr_rendezvous("集合點");

    lr_start_transaction("登陸時間");
    web_submit_form("login.pl", 
        "Snapshot=t2.inf", 
        ITEMDATA, 
        "Name=username", "Value=test1", ENDITEM, 
        "Name=password", "Value=123456", ENDITEM, 
        "Name=login.x", "Value=59", ENDITEM, 
        "Name=login.y", "Value=5", ENDITEM, 
        LAST);
    lr_end_sub_transaction("登陸時間",LR_ABORT);

    return 0;
}  
技術分享圖片

  上面的代碼中有大括號“{}”,返回函數“ return ”,如果你有編程基礎的不會說對於上面的代碼一點都看不懂。只是上面的腳本沒有使用我們平時用到的東西,如定義常量、變量,分支(if....else if....)、循環語句(for...)

  下面我們動手寫個小程序,一個乘法運算,求員工工資的總合。

技術分享圖片
#define COUNT 100
#define SALARY 4000

Action()
{
    int total;
    total = COUNT * SALARY;
    lr_output_message("100人合計薪資支出為:%d",total);

    return 0 ;
}
技術分享圖片

#define COUNT 100

#define SALARY 4000 定義一個全局常量。

lr_output_message 輸出語句,這個和我們所學的C 語言不一樣,在C中我們會用println 來輸入結果。

運行結果:

技術分享圖片
..........
Starting iteration 1. Starting action Action. Action.c(9): 100人合計薪資支出為:400000 ----這裏將運行結果打印輸出 Ending action Action. Ending iteration 1.
..........
技術分享圖片

一個有意思的小程序

  當然了,上面的程序太雞肋了,我只是想表達,loadrunner 也可以運行我們上學時學的那些普通的小程序。他們是一樣一樣的。

下面看個比較有意思的小程序,通過隨即數和分支(選擇)語句switch來完成

技術分享圖片
Action()
{
    int randomnumber;   
    randomnumber = rand() % 3+1;

    switch (randomnumber) {
    
    case 1:
        {
            lr_rendezvous("訪問百度集合點");

            web_url("www.baidu.com", 
        "URL=http://www.baidu.com/", 
                "Resource=0", 
                    "RecContentType=text/html", 
                    "Referer=", 
                    "Snapshot=t12.inf", 
                    "Mode=HTML", 
                    EXTRARES, 
                    "Url=http://s1.bdstatic.com/r/www/img/i-1.0.0.png", ENDITEM, 
                    "Url=/favicon.ico", "Referer=", ENDITEM, 
                    "Url=http://s1.bdstatic.com/r/www/img/bg-1.0.0.gif", ENDITEM, 
                    LAST);

            return 0;

        }

    case 2:
        {
            lr_rendezvous("訪問谷歌集合點");

            web_url("www.google.com.hk", 
                    "URL=http://www.google.com.hk/", 
                    "Resource=0", 
                    "RecContentType=text/html", 
                    "Referer=", 
                    "Snapshot=t10.inf", 
                    "Mode=HTML", 
                    EXTRARES, 
                    "Url=http://ssl.gstatic.com/gb/images/b_8d5afc09.png", ENDITEM, 
                    "Url=/images/srpr/logo3w.png", ENDITEM, 
                    "Url=/extern_chrome/749e1ce3c3e5f171.js", ENDITEM, 
                    "Url=/images/swxa.gif", ENDITEM, 
                    "Url=/favicon.ico", "Referer=", ENDITEM, 
                    "Url=http://ssl.gstatic.com/gb/js/sem_0e1289051da7e9e3697c2025d9490acd.js", ENDITEM, 
                    "Url=http://www.google.com/textinputassistant/tia.png", ENDITEM, 
                    LAST);

            return 0;

        }
    case 3:
        {
            lr_rendezvous("訪問有道集合點");

            web_url("www.youdao.com", 
                    "URL=http://www.youdao.com/", 
                    "Resource=0", 
                    "RecContentType=text/html", 
                    "Referer=", 
                    "Snapshot=t7.inf", 
                    "Mode=HTML", 
                    EXTRARES, 
                    "Url=http://shared.ydstatic.com/oxo/p/pic.gif", ENDITEM, 
                    "Url=http://shared.ydstatic.com/oxo/p/logo.png?1", ENDITEM, 
                    "Url=http://shared.ydstatic.com/oxo/p/nv_line.gif", ENDITEM, 
                    "Url=http://shared.ydstatic.com/r/2.0/p/pic.gif", ENDITEM, 
                    LAST);

            return 0;
        }
         
    }
    
}   
技術分享圖片

上面的程序,我分別錄制了百度、谷歌、有道訪問三個網的首頁的代碼,我想在運行腳本時,隨機的去訪問其中一個網站,如何做呢?我們通過隨機函數,隨機出1~3之間的整數,根據隨機來的結果,然後執行switch語句中的代碼。

下面來看我的結果

  為了查看腳本結果更清晰,我在每一段腳本前面加了一個集合點“lr_rendezvous”函數。

技術分享圖片
Starting iteration 1.
Starting action Action.
Action.c(57): Rendezvous 訪問有道集合點
Action.c(59): Downloading resource "http://shared.ydstatic.com/oxo/p/pic.gif" (specified by argument number 9)      [MsgId: MMSG-26577]
Action.c(59): Downloading resource "http://shared.ydstatic.com/oxo/p/logo.png?1" (specified by argument number 11)      [MsgId: MMSG-26577]
Action.c(59): Downloading resource "http://shared.ydstatic.com/oxo/p/nv_line.gif" (specified by argument number 13)      [MsgId: MMSG-26577]
Action.c(59): Downloading resource "http://shared.ydstatic.com/r/2.0/p/pic.gif" (specified by argument number 15)      [MsgId: MMSG-26577]
Action.c(59): Found resource "http://shared.ydstatic.com/dao/search/outweb/js/yd.js?201207131" in HTML "http://www.youdao.com/"      [MsgId: MMSG-26659]
Action.c(59): Found resource "http://shared.ydstatic.com/dao/search/outweb/js/nav.js?201207131" in HTML "http://www.youdao.com/"      [MsgId: MMSG-26659]
Action.c(59): Found resource "http://shared.ydstatic.com/dao/search/outweb/js/suggest.js?201207131" in HTML "http://www.youdao.com/"      [MsgId: MMSG-26659]
Action.c(59): web_url("www.youdao.com") was successful, 30006 body bytes, 3347 header bytes, 39 chunking overhead bytes      [MsgId: MMSG-26385]
Ending action Action.
Ending iteration 1.
技術分享圖片

通過腳本讀取文件

  為了增加語言的強大,高級語言不可以把一個程序的實現從頭到尾寫到文件裏,這樣可讀性和維護很差,也無法實現團隊發,肯定會相互調用接口函數庫等。當然,讀取文件也是常用的操作,下面我們來看一個讀取文件的例子。

我們事先準備一個文件test.txt ,裏面隨便你輸入些什麽內容吧!

技術分享圖片
Action()
{

    int count,total=0;
    char buffer [50];
    long file_stream;
    char * filename = "C:\\test.txt";  //讀取文件的存放位置

    //判斷是否可以讀取文件
    if((file_stream =fopen(filename,"r"))==NULL)   
    {
        lr_error_message("不能打開%s文件!",filename);

        return -1;
    }

    while(!feof(file_stream))
    {
        count=fread(buffer,sizeof(char),50,file_stream);  //從文件中讀取50個字符
        total=total+count;   //字符個數計數
        if(total>=50)
        {
            fclose(file_stream);  //關閉文件
            lr_output_message("文件的前50字符:%s",buffer);
            break;  //退出循環
        }

    }
    return 0;
}
技術分享圖片

上面的代碼中我加了註釋,這裏沒必須再做解釋。

下面來看我的運行結果

Starting iteration 1.
Starting action Action.
Action.c(24): 文件的前50字符:01234567890123456789012345678901234567890123456789
Ending action Action.
Ending iteration 1.

loadrunner難麽? 對於有編程基礎的一點都不難。我們所要做的就是熟悉loadrunner的常用函數罷了。

(二)

 今天有朋友問我,關於loadrunner腳本編第二篇什麽時候寫,我告訴他都沒什麽東西了。要學習一門語言,基本的語法和思想很重要。現在每個人都識字,那是不是每個識字的人都可以當作家。不可能,因為大多數人沒有作家的思想。編程是一門藝術,我們可以把代碼寫得很優美,而中國的程序員為什麽叫代碼工人呢?國為國外的程序員在寫一篇優美的“散文”,中國的程序員在寫“說明文”。中國的程序員只是根據需求把一個產品通過語言描述清楚。

  扯遠了,最近變啰嗦了,呵呵!我想表達的意思就是行編程基本語法必須要記牢。程序的思想也很重要。因為我在編程上面也是個半調子。所以看我的文章也只能算回味一下語法了。

下面來回顧一下嵌套循環例子。

技術分享圖片
Action()
{
    int  i,j;   //生命兩個變量
    for (i=1;i<=5;i++)   //第一重循環,循環5次
    {
        if (i==3)    
            break;   //當i等於3時,跳出本重循環
        else
             lr_output_message("i=%d",i);  //否則,輸入i的值

        for (j=1;j<=5;j++)  //第二重循環,循環5次
        {
            if (j==2)   
                break;   //當j等於2時,跳出本重循環
            else
             lr_output_message("j=%d",j);  //否則,輸入j的值
        }
    }
}
技術分享圖片

上面的代碼中我加了註釋,這裏就不用再解釋。

運行結果:

技術分享圖片
Starting iteration 1.
Starting action Action.
Action.c(9): i=1
Action.c(16): j=1
Action.c(9): i=2
Action.c(16): j=1
Ending action Action.
Ending iteration 1.
技術分享圖片

函數

  函數,通常 一小段C語言程序僅有一個main()函數組成。然而,在實際編寫應用程序中,需要開發人員編寫大量的用戶自定交函數,不僅要在程序中定義函數本身,而且在主調函數模塊中還必須對該被調函數進行類型說明,然後才能使用,與用戶自定義函數相對應的是函數庫,C語言集成開發環境(IDE)提供,我們只要調用就是行了。就就所謂前人種樹,後人乘涼,不然看似一個簡單的東西,尋其源頭來做,都是一個相當復雜的過程。

技術分享圖片
void SsyHello()  //打招呼函數
{
    lr_output_message("hello %s",lr_get_host_name());
}

int GetBigger(int x,int y)  //得到最大值函數
{
    if (x>y) {
        return x;
    }
    else{
        return y;
    }

}

Action(){
    int x=10,y=20, result;   //聲明變量

    SsyHello();  //無形參,無返回值函數
    result = GetBigger(x,y);
    lr_output_message("GetBigger(%d,%d)=%d",x,y,result);  //帶形參,帶返回值函數

    return 0;
}
技術分享圖片

上面的程序加註解了,簡單來說就是前面定義了兩個函數SsyHello() 和 GetBigger(),主函數Action()對前面兩個函數進行調用。

運行結果:

技術分享圖片
Starting iteration 1.
Starting action Action.
Action.c(4): hello 2011-20120624YO
Action.c(23): GetBigger(10,20)=20
Ending action Action.
Ending iteration 1.
技術分享圖片

動態存儲方式與靜態存儲方式

  

  我們在定義變量是,根據定義的位置不同,分為全局變量與局部變量。我出生在一個叫“舞陽”的小縣城,在這個縣城中也有人名“舞陽”,前一個作用於整個縣城,後一個只作用於他個人。那麽從變量值的存在生存期角度,又可分為靜態存儲方式和動態存儲方式兩類。

靜態存儲方式:是指在程序運行期間分配固定的存儲空間方式。

動態存儲方式:是在程序運行期間根據需要進行動態的分配存儲空間的方式。

用戶存儲空間可分三部分:

1、程序區

2、靜態存儲區

3、動態存儲區

全局變量全部存放在靜態存儲區,在程序開始執行時給全局變量分配存儲區,程序運行完畢就釋放,在程序執行過程中它們占據固定的存儲單元,而不動態地進行分配和釋放。

動態存儲區存放以下數據

(1)函數形式參數

(2)自動變量(未加static聲明的局部變量)

(3)函數調用時的現場保護和返回地址

上面這些數據,在函數開始調用時分配動態空間,函數結果時釋放這些空間。

在C語言中,每個變量和函數有兩個屬性:數據類型和數據的存儲類別

* 自動(auto)變量

函數中的局部變量,如不專門的聲明為static存儲類別,都是動態地分配存儲空間的。

* 靜態(static)聲明局部變量

有時希望函數中的局部變量的值在函數調用結束後不消失而保留,這時就應該指定局部變量為“靜態局部變量”,用static關鍵字。

* 寄存器(register)變量

為了提高效率,C語言允許把局部變量的值放在CPU中的寄存器中,這種變量叫“寄存器變量”,用關鍵字register變量。

技術分享圖片
static int c;

int prime(register int number)   //判斷是否為素數
{
    register int flag=1;
    auto int n;
    for (n=2;n<number/2 && flag==1;n++) {
        if (number % n==0) flag=0;
    return(flag);    
        
    }
}

demo(int a)    //static、auto變量的演示函數
{
    auto int b=0;
    int d;
    static c=3;
    b=b+1;
    c=c+1;
    lr_output_message("demo()函數中的d=%d",d);
    lr_output_message("demo()函數中的static c=%d",c);
    return a+b+c;

}
Action(){
    int a=2,i;   //變量聲明

    for (i=0;i<3;i++) {
        lr_output_message("demo()函數部分第%d運行情況如下:",i+1);
        lr_output_message("函數demo運行結果為:%d",demo(a));
        lr_output_message("-------------------\n\r");
    }

    //判斷13是否為素數,並輸出提示信息
    if (prime(13)==0)
        lr_output_message("13不是素數!");
    else
        lr_output_message("13是素數!");

    lr_output_message("c=%d",c);  //輸入變理的值

     
    return 0;
}
技術分享圖片

  素數:指大於1的自然數,除了1和它本身不能被其它數整除的數。prime()函數部分主要用來判斷傳入的數是否是素數。

  demo()函數用來做static和auto類型的變量演示。Action()函數用於調用與輸入結果。

運行結果

技術分享圖片
Starting iteration 1.
Starting action Action.
Action.c(31): demo()函數部分第1運行情況如下:
Action.c(22): demo()函數中的d=51446257
Action.c(23): demo()函數中的static c=4
Action.c(32): 函數demo運行結果為:7
Action.c(33): -------------------

Action.c(31): demo()函數部分第2運行情況如下:
Action.c(22): demo()函數中的d=51446257
Action.c(23): demo()函數中的static c=5
Action.c(32): 函數demo運行結果為:8
Action.c(33): -------------------

Action.c(31): demo()函數部分第3運行情況如下:
Action.c(22): demo()函數中的d=51446257
Action.c(23): demo()函數中的static c=6
Action.c(32): 函數demo運行結果為:9
Action.c(33): -------------------

Action.c(40): 13是素數!
Action.c(42): c=0
Ending action Action.
Ending iteration 1.
技術分享圖片

指針

  指針是C語言中廣泛使用的一種數據類型,指針可以使我們的程序變得非常靈活,但也讓不少程序員頭痛,一不小心就會使程序出錯。

  指針一般指向一個函數或一個變量。在使用一個指針時,一個程序既可以直接使用這個指針所儲存的內存地址,又可以使用這個地址裏儲存的變量或函數的值。

  有一本很厚小說,為了便於讀者找到某一段內容,我們會給某一段內容起一個小標題並標註上頁數。這樣找起來就非常方便了。那在內存中,小標題頁數就相當於內存單元的指針,具體的小說內容就是內存單元的內容。

技術分享圖片
Action(){
    int score[5]={100,98,78,55};   //一維數組
    int *p=score;         //一維數組指針
    int sixnum[2][3]={{1,2,3},{4,5,6}};  //二維數組
    int (*p1)[3];        //二維數組指針
    int i,j;      //定義兩個變量

    for (i=0;i<=4;i++) {
        lr_output_message("score[%d]=%d",i,score[i]);  //以下標形式標識數組
        lr_output_message("*(p++)=%d",*(p++));   //以指針方式輸出數組
    }
    lr_output_message("--------------------------");

    p=score;
    for (i=0;i<=4;i++) {
        lr_output_message("score[%d]=%d",i,score[i]);  //以下標形式標識數組
        lr_output_message("*(p+%d)=%d",*(p+i));   //以指針方式輸出數組
    }
    lr_output_message("--------------------------");

    p1=sixnum;
    for (i=0;i<=1;i++) {
        for (j=0;j<=2;j++) {
             lr_output_message("sixnum[%d][%d]=%d",i,j,sixnum[i][j]);   //以下標形式標識數組
             lr_output_message("*(*(p1+%d)+%d)=%d",*(*(p1+i)+j));  //以指針方式輸出數組
        }

    }
    
    return 0;
}
技術分享圖片

運行結果

技術分享圖片
Starting iteration 1.
Starting action Action.
Action.c(11): score[0]=100
Action.c(12): *(p++)=100
Action.c(11): score[1]=98
Action.c(12): *(p++)=98
Action.c(11): score[2]=78
Action.c(12): *(p++)=78
Action.c(11): score[3]=55
Action.c(12): *(p++)=55
Action.c(11): score[4]=0
Action.c(12): *(p++)=0
Action.c(14): --------------------------
Action.c(18): score[0]=100
Action.c(19): *(p+100)=0
Action.c(18): score[1]=98
Action.c(19): *(p+98)=0
Action.c(18): score[2]=78
Action.c(19): *(p+78)=0
Action.c(18): score[3]=55
Action.c(19): *(p+55)=0
Action.c(18): score[4]=0
Action.c(19): *(p+0)=0
Action.c(21): --------------------------
Action.c(26): sixnum[0][0]=1
Action.c(27): *(*(p1+1)+0)=54385392
Action.c(26): sixnum[0][1]=2
Action.c(27): *(*(p1+2)+0)=54385392
Action.c(26): sixnum[0][2]=3
Action.c(27): *(*(p1+3)+0)=54385392
Action.c(26): sixnum[1][0]=4
Action.c(27): *(*(p1+4)+0)=54385392
Action.c(26): sixnum[1][1]=5
Action.c(27): *(*(p1+5)+0)=54385392
Action.c(26): sixnum[1][2]=6
Action.c(27): *(*(p1+6)+0)=54385392
Ending action Action.
Ending iteration 1.
技術分享圖片

原文:

蟲師博客:https://www.cnblogs.com/fnng/archive/2012/07/15/2592344.html
蟲師博客:https://www.cnblogs.com/fnng/archive/2012/07/21/2601973.html

LoadRunner腳本編寫