先声明,目前属于学了没几天的新手,以下部分都是自己研究加上网上资料所得,如果有问题请各位达人指出。
前一阵子写了一段调用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;
}
//取得数据
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 确定里面的内容。
这个很恶心,做循环的时候容易多取条数据,害的我还改了一下循环语句。