一、脚本调试
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工具:
soatest\soupui(既能做功能又能测性能)
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" + "\t" + "user_id1"+ "\t" + "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") + "\t"+ rs.getString("user_id1")+"\t"+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实现的效果比较好,因不需要频繁的连接关闭数据库。
------------------------------------------------------------------------