一、腳本調試
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實現的效果比較好,因不需要頻繁的連接關閉數據庫。
------------------------------------------------------------------------