loadrunner学习笔记(从MYSQL中取数据)

2010-08-27  徐明明 

先声明,目前属于学了没几天的新手,以下部分都是自己研究加上网上资料所得,如果有问题请各位达人指出。

前一阵子写了一段调用MYSQL的测试代码。功能很简单,就是从数据库里取数据,然后打印出来。算是为以后的脚本做个SAMPLE。

本机环境配置如下:

WINDOWS XP SP2

LOADRUNNER8.0

MYSQL5.0

服务器:

linux

大家都知道,LR是没办法录制MYSQL的。我用了各种查询分析器,要不是不能用,要不是报错。所以干脆就自己写脚本。

手动写脚本钱先介绍一下几个文件:

print.inl

网上找的一个解释是:打印表格使用的函数。录制脚本时才有用,写脚本的话没有用。

我的理解:针对如lrd_fetch函数,其中有一个指向函数的指针,这里面的内容得在print.inl里定义,不然会取不到数据。

这也可能只是针对MYSQL的情况,或者是有其他办法解决,望高手指点。


vdf.h

把变量都定义在这里,看扩展名就知道,是头文件。

pre_cci.c

看这个.c的文件就知道是放c的代码啦。

网上找的解释是:整个录制脚本的程序全部写在这里,可以在这里查看完整的函数过程。

我的理解:这一看就是c编译时生成的文件,把所有的头文件之类的东西都合并在一起的那挫东西。在LR基本上是不用看的,不过有些时候问题出现在print.inl这类文件里时,就可以在这里找一下。

globals.h

从名字意思上来看是定义全局变量的头文件。具体如何执行还得研究一下,我是把某些函数会调用到的头文件放在了里面。比如lrun.h或者web_api.h之类的。一般你选择协议后会自动在里面生成,不过有时候用到其他协议的函数时,得把相关的头文件给添加进去。

XXXXX.usr文件

网上找的解释:此文件是loadrunner 插件自动生成的文件,该文件是在Lr Controler工具中所要选择的脚本。

我的理解:按扩展名的意思差不多是用户信息配置文件。具体一些配置怎么改还没深刻研究,反正我写脚本就只用到了3个东西。AdditionalTypes,ActiveTypes,GenerateTypes。

LoadRunnerVuser.prm

网上找的解释:此文件记录了脚本中所有的参数,以及参数的属性,具体某个参数的值是在.dat文件中记录的。.

我的理解:LR不是有参数化嘛,这东西就是记录了参数化的一些信息。具体不用去管他,在LR中参数化后自己会配置好。但是如果想把以前脚本的参数化信息拷贝过来,别忘了不光要把.dat文件拷贝,还要把这个文件拷贝过来。或者你牛叉的话根据里面的信息写过去就是了。。。

至于XXX.rdf、XXX.grd啥的我也不清楚具体用处。

从扩展名的意思上理解前者是专门描述WEB上资源信息的东西,后者我也不清楚,没很有很明确的解释。或者是“狗_日_的”的意思?

还有一些如debug.XXX、default.XXX的没什么必要看,反正LR都是自己配置好的。

文件介绍完,说一下代码,如下:

Action.c

Action()

{

unsigned long rownum;

//初始化

lrd_init(&InitInfo, DBTypeVersion);

//打开上下文

lrd_open_context(&Ctx1, LRD_DBTYPE_ODBC, 0, 0, 0);

//申请连接的内存

lrd_alloc_connection(&Con1, LRD_DBTYPE_ODBC, Ctx1, 0 /*Unused*/, 0);

//打开连接

lrd_open_connection(&Con1, LRD_DBTYPE_ODBC, "", "","", "DRIVER=MySQL ODBC 5.1 Driver;UID=登录名;PWD=密码;SERVER=数据库的地址;charset=GBK;DATABASE=", Ctx1, 1, 0);  

//打开游标

lrd_open_cursor(&Csr1, Con1, 0);

//Sql语句

lrd_stmt(Csr1, "SELECT user_id,user_name,user_pwd FROM test.USER_INFO;", -1, 1, 0 , 0);

//统计行数到count变量中

lrd_row_count(Csr1, &count, 0);

//取得数据

lrd_save_col(Csr1, 2, 1, 0, "name");

lrd_save_col(Csr1, 3, 1, 0, "pwd");

//移动游标

lrd_fetch(Csr1, 1, 1, &rownum, PrintRow1, 0);

//打印出取得的数据

lr_output_message("name = [%s]", lr_eval_string("{name}")); 

lr_output_message("pwd = [%s]", lr_eval_string("{pwd}")); 

//先关闭游标  

lrd_close_cursor(&Csr1, 0);  

//再关闭连接  

lrd_close_connection(&Con1, 0, 0);  

//释放连接,和alloc相呼应,否则有内存泄露  

lrd_free_connection(&Con1, 0, 0);  

//再关闭上下文  

lrd_close_context(&Ctx1, 0, 0);  

}

vdf.h

/* vdf.h */

#ifndef VDF_H

#define  VDF_H

#define LRD_RECORDED_UNDER_WIN32

#include "lrd.h"

//初始化需要用的东西

static LRD_INIT_INFO InitInfo = {LRD_INIT_INFO_EYECAT};  

static LRD_DEFAULT_DB_VERSION DBTypeVersion[] =  

{  

  {LRD_DBTYPE_ODBC, LRD_DBVERSION_ODBC_30},  

  {LRD_DBTYPE_NONE, LRD_DBVERSION_NONE}  

};  

//这三兄弟么就和就是Action.c里面需要用到的游标和链接啥的

static LRD_CONTEXT FAR * Ctx1;  

static LRD_CONNECTION FAR * Con1;  

static LRD_CURSOR FAR *     Csr1; 

//以下都是lrd_fetch内指向函数的指针会用到的东西,在print.inl里调用。

static unsigned long        uliActualLength;

static LRD_VAR_DESC    NEWS_USER_ID_D1 =

    {LRD_VAR_DESC_EYECAT, 1, 2050, LRD_DBTYPE_ODBC, {0, 0, 0}, DT_SZ};

static LRD_VAR_DESC    NEWS_USER_NAME_D2 =

    {LRD_VAR_DESC_EYECAT, 1, 2050, LRD_DBTYPE_ODBC, {0, 0, 0}, DT_SZ};

static LRD_VAR_DESC    NEWS_USER_PWD_D3 =

    {LRD_VAR_DESC_EYECAT, 1, 92, LRD_DBTYPE_ODBC, {0, 0, 0}, DT_SZ};

print.inl

#ifndef INL_H

#define  INL_H


//lrd_fetch内的指针所指向的函数

LRD_PRINT_ROW_PROTO(PrintRow1)

{

    LRDRET gjLRDRet = LRDRET_I_OK;

    char szUSER_ID_D1[256];

    char szUSER_NAME_D2[256];

    char szUSER_PWD_D3[256];

    

    //设置指向特定列的数据的指针,只访问数据,不执行绑定操作。

    lrd_col_data(Csr1, 1, 0, &NEWS_USER_ID_D1, &uliActualLength, 0);

    lrd_col_data(Csr1, 2, 0, &NEWS_USER_NAME_D2, &uliActualLength, 0);

    lrd_col_data(Csr1, 3, 0, &NEWS_USER_PWD_D3, &uliActualLength, 0);

    //将变量或数组转换成可打印字符串

    lrd_to_printable(&NEWS_USER_ID_D1, muliRowIndex, szUSER_ID_D1, 256, "");

    lrd_to_printable(&NEWS_USER_NAME_D2, muliRowIndex, szUSER_NAME_D2, 256, "");

    lrd_to_printable(&NEWS_USER_PWD_D3, muliRowIndex, szUSER_PWD_D3, 256, "");

    //我也不知道为什么要加这段,反正参考其他录制好的文件里是有这段的,那就加呗。希望达人告知原因。

    lr_debug_message(LR_MSG_CLASS_RESULT_DATA, " %s, %s, %s",  szUSER_ID_D1, szUSER_NAME_D2,szUSER_PWD_D3);

    return gjLRDRet;

}


#ifndef CCI
BEGIN_VUSER_DECLARATION
    DECLARE_VUSER_RUN("Vuser Run", Actions)
END_VUSER_DECLARATION
#endif

#endif

以上3个文件时最关键的,但是执行时会报初始化错误,找了半天才发现还得改一个文件。
XXX.usr

我只改了一下3个地方,因为录制的是WEB+MYSQL的脚本,所以用的是ODBC+OTWeb。
AdditionalTypes=ODBC,QTWeb
ActiveTypes=ODBC,QTWeb
GenerateTypes=ODBC,QTWeb
最后还有个小地方得提醒一下

//取得数据

lrd_save_col(Csr1, 2, 1, 0, "name");

lrd_save_col(Csr1, 3, 1, 0, "pwd");

//移动游标

lrd_fetch(Csr1, 1, 1, &rownum, PrintRow1, 0);

//打印出取得的数据

lr_output_message("name = [%s]", lr_eval_string("{name}")); 

lr_output_message("pwd = [%s]", lr_eval_string("{pwd}")); 

这段话里,代码是先用lrd_save_col 取数据库里的数据,然后再用lrd_fetch 确定里面的内容。

这个很恶心,做循环的时候容易多取条数据,害的我还改了一下循环语句。

687°/6879 人阅读/0 条评论 发表评论

登录 后发表评论