一、脚本调试
1、回放调试脚本慢,可进行如下设置:
2、bbs回帖脚本调试心得:
思路
①练习先进行tid的关联。回帖需要关联用户id,模块id(fid),帖子(tid)id,但是就登录回帖这个需求,可以在同一个帖子下进行回帖,而不会影响压测的结果,所以,fid和tid都无需进行关联,写死即可;
②在关联上tid后,访问回帖请求,报登录连接不上,先将问题放置。
③对回帖请求中的参数formhash进行关联。在tree视图中,查找产生formhash的请求,进行关联。注意在进行右键关联时,找左右边界相同多的那个值进行关联,这样比较容易命中,而且要注意有特殊需要转义的字符,需要进行转义,也可以用其它的值来进行关联,从而避开转义。
④调试过程中,在找关联关系时,在tree视图中的录制请求视图(display recorded snapshot)查看,回放错误时,结合tress视图中的回放请求视图(show replay snapshot)查看,此处可以查看发送请求的状态是否成功。
⑤脚本回放报错后,除了查看报错信息之外,关注报错信息附近的warning信息或许会对调试有帮助。
⑥脚本调试是个循序渐进的过程,一定不能急躁,相信自己,关联的调试,无外乎就是左右边界值的调整和请求响应值的对应关系,其它业务流程的依赖关系则要具体情况具体分析。
3、一些名词:
①事务:是自己定义的,其设置尽可能的精确,测什么就放什么(OA工作流之类的例外);
②思考时间:
加在事务的外边
为什么要加思考时间 → 实质是缓解服务器压力,减少单位时间段内向发送到服务器请求数
一般压力测试不加思考时间,有的时候为了测试报告好看,不加思考时间,并发量达不到,因单位时间内的请求量过大,服务器处理不过来,这时候,会产生阻塞和错误。虽然还是100个并发,但是加了思考时间,服务器的压力就会减小了。并发量达不到要求,又要上线的时候,加上(哈哈,没节操!)
加了思考时间,tps会降低,前提是服务器的tps没有达到极限,如果服务器的tps达到了极限,加思考时间和不加思考时间没有区别(木桶原理)
设置思考时间是否生效:
什么影响服务器的处理能力呢?cup,一个cpu单核的,一次只能处理一件事(线程)
pacing也是思考时间,作用于迭代和迭代之间,相对来说think_time比较灵活
③检查点:从请求的返回结果集中取值
检查点是否一定要加:
理论上来说,检查点函数是一定要加的(性能测试的前提条件是请求成功,符合业务规则)
加检查点会影响性能:
A、对于写操作来说不加检查点,只需要在场景运行结束后,比对数据库中的数据和通过的事务数(通过的事务数可以在在controller中通过的事务数选项查看)
B、对于查操作来说需要加检查点
④集合点:
集合点策略百分比,模拟瞬时并发
什么时候用:秒杀项目、抢购项目(有些抢购就是一个静态页面,汗颜!!!)
目的:更加真实的模拟用户的瞬时并发概率
4、关于脚本精简
①性能测试的服务对象是开发,在脚本开发中,可以不考虑图片、css、js等样式;
②搞清楚关联和依赖关系,哪些是必须的,哪些是依赖的,必须+依赖的请求,其他的请求都可以精简掉;
③实际测试中,建议一个action里只放一个事务,即只放一个请求。
二、脚本开发
1、http脚本的开发
APP本身就相当于web的前端,都有一个服务器,一般是做http协议通信
接口说明文档
①http接口测试一般用postman;
②所有走https的协议在lr上,都可以用火狐进行录制;
③api脚本回放报错时,如果报安全协议(SSL)错误,在请求前加上:
web_set_sockets_option("SSL_VERSION","TLS"); //走https协议
④接口测试(http请求、手机接口测试)手写,用如下两个函数:
web_custom_request
web_submit_data
手写豆瓣api请求:
A、使用web_custom_request函数
B、使用web_submit_data函数
如下图这么写时,报错:
故上述脚本修改如下:
将下图打开可以查看返回结果:
2、webservice脚本的开发
回放脚本:
添加新的函数:
3、接口功能测试webserver工具:
soatestsoupui(既能做功能又能测性能)
4、实现mysql的增删改查脚本:
方式一、
1 javauser: 2 /* 3 * LoadRunner Java script. (Build: _build_number_) 4 * 5 * Script Description: 6 * 7 */ 8 import java.sql.Connection; 9 import java.sql.DriverManager; 10 import java.sql.ResultSet; 11 import java.sql.SQLException; 12 import java.sql.Statement; 13 import com.sun.org.apache.xpath.internal.operations.String; 14 import lrapi.lr; 15 16 17 public class Actions 18 { 19 20 public int init() throws Throwable { 21 22 Class.forName("com.mysql.jdbc.Driver");// 加载驱动程序 23 24 String url = "jdbc:mysql://10.10.10.10:36001/message";// URL指向要访问的数据库名message_old 25 26 String user = "root";// MySQL配置时的用户名 27 28 String password = "############";// MySQL配置时的密码 29 30 Connection connection = DriverManager.getConnection(url, user,password);// 连续数据库 31 32 if (!connection.isClosed()){ 33 34 System.out.println("Succeeded connecting to the Database!"); 35 } 36 37 Statement statement = connection.createStatement();// statement用来执行SQL语句 38 39 System.out.println("initial_id" + " " + "user_id1"+ " " + "user_id2"); 40 41 return 0; 42 }//end of init 43 44 public int action() throws Throwable { 45 46 String sql ="SELECT * from user WHERE user_id1=238 group by user_id1"; 47 ResultSet rs = statement.executeQuery(sql);// 执行SQL语句并返回结果集 48 49 while (rs.next()) { 50 51 System.out.println(rs.getString("initi_id") + " "+ rs.getString("user_id1")+" "+rs.getString("user_id2")); 52 53 } 54 55 return 0; 56 } 57 58 59 public int end() throws Throwable { 60 61 rs.close();//关闭果集 62 connection.close();//数据库连接 63 64 return 0; 65 }//end of end 66 67 }
方式二、
init中的代码:
1 #include "Ptt_MySql.h" 2 vuser_init() 3 { 4 5 lr_load_dll("libmysql.dll"); 6 7 #define MYSQLSERVER "192.168.2.104" 8 #define MYSQLUSERNAME "root" 9 #define MYSQLPASSWORD "123456" 10 #define MYSQLDB "mysqlwork1" 11 #define MYSQLPORT "3306" 12 return 0; 13 }
action中的代码:
1 char sqlQuery[512]; 2 MYSQL *Mconnection ; 3 int MyRc ; 4 5 char *tempname ; 6 7 char tempname2[100]; 8 9 Action() 10 { 11 12 13 Mconnection = lr_mysql_connect(MYSQLSERVER , MYSQLUSERNAME , MYSQLPASSWORD , MYSQLDB , atoi(MYSQLPORT)); 14 15 16 sprintf(sqlQuery, "insert into Student ( name, sex , birth , department , address) values ( '张三' , '男' , 1987 , '计算机' , '北京' )"); 17 18 lr_mysql_query(Mconnection, sqlQuery); 19 20 21 sprintf(sqlQuery , "update Student set name='王五' where name='张三' "); 22 23 lr_mysql_query(Mconnection, sqlQuery); 24 25 26 27 sprintf(sqlQuery, "select id, name, sex , birth , department , address from Student where name = '王五' "); 28 29 lr_mysql_query(Mconnection, sqlQuery); 30 31 32 //row[x][y].cell x表示列(第一列是0),y表示行(第一行是0)。 33 lr_save_string(row[0][0].cell, "id"); 34 35 /* 36 lr_convert_string_encoding(row[1][0].cell ,"utf-8" ,NULL,"tempname"); 37 strcpy(tempname2,lr_eval_string("{tempname}")), 38 lr_save_string(tempname2,"sname"); 39 lr_output_message(lr_eval_string("name: {sname}")); 40 */ 41 42 lr_save_string(row[1][0].cell, "sname"); 43 44 lr_save_string(row[2][0].cell, "sex"); 45 46 lr_save_string(row[3][0].cell, "birth"); 47 48 lr_save_string(row[4][0].cell, "department"); 49 50 51 lr_save_string(row[5][0].cell, "address"); 52 53 54 lr_output_message(lr_eval_string("id: {id}")); 55 56 lr_output_message(lr_eval_string("name: {sname}")); 57 58 lr_output_message(lr_eval_string("sex: {sex}")); 59 60 lr_output_message(lr_eval_string("birth: {birth}")); 61 62 lr_output_message(lr_eval_string("department: {department}")); 63 64 lr_output_message(lr_eval_string("address: {address}")); 65 66 67 68 69 70 sprintf(sqlQuery , "delete from Student where name='王五' "); 71 72 lr_mysql_query(Mconnection, sqlQuery); 73 74 //Disconnect from MySQL #断开数据库连接 75 lr_mysql_disconnect(Mconnection); 76 77 return 0; 78 }
连接jdbc增删改查用jemter实现的效果比较好,因不需要频繁的连接关闭数据库。
------------------------------------------------------------------------