在使用JMeter進行測試的過程中,有時候需要將測試結果寫入到Excel檔案,本篇文章將詳細說明具體步驟。
把測試結果寫入Excel檔案中操作思路分析:
(1)準備需要的環境
- 引入操作Excel檔案的基礎JAR包:
jxl.jar
。 - 封裝自定義操作Excel的JAR包
- Excel中一般有三個要素:
workbook
,sheet
,cell
。
要想把結果儲存到指定的單元格中,那麼就必須要確定好這三個元素依次來定位。
1)先獲取Excel的檔名。
2)獲取表單名。
3)獲取單元格的座標。 - 獲取結果,寫入到對應的單元格里面去。
- 需要利用BeanShell編寫Java程式碼,獲取對應的資料寫入到Excel裡面去。
- Excel中一般有三個要素:
(2)準備需要的資料檔案。
(3)編寫JMeter指令碼,新增需要的元件,並控制元件的執行順序,完成最終的測試。
1、環境準備
(1)引入操作Excel檔案的基礎JAR包
- 需要使用第三方jar包:
jxl.jar
。 jxl.jar
的作用:完成對Excel檔案的讀寫以及修改操作。- 下載好之後,放到JMeter的安裝路徑下的
lib
目錄下。
(2)引入封裝自定義操作Excel檔案的JAR包
我們可以使用Java語言,對jxl.jar
包的功能,進行自定義封裝,定製成我們自己需要功能。
然後把封裝好的程式碼,打成JAR包,放入到JMeter安裝目錄下的lib\ext
目錄下。
簡易自定義封裝程式碼如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import jxl.Cell;
import jxl.JXLException;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Colour;
import jxl.format.VerticalAlignment;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
public class CWOutputFile {
/**
* wOutputFile 作用:把內容寫入到Excel檔案中。
* wOutputFile寫結果檔案 wOutputFile(檔案路徑、用例編號、用例標題、預期結果、實際結果、測試結果)
* @throws IOException
* @throws BiffException
* @throws WriteException
*/
public void wOutputFile(String filepath,String caseNo,String testPoint,String testData,String preResult,String fresult) throws BiffException, IOException, WriteException{
File output=new File(filepath);
String result = "";
InputStream instream = new FileInputStream(filepath);
Workbook readwb = Workbook.getWorkbook(instream);
WritableWorkbook wbook = Workbook.createWorkbook(output, readwb); //根據檔案建立一個操作物件
WritableSheet readsheet = wbook.getSheet(0); //定位到檔案的第一個sheet頁籤
int rsRows = readsheet.getRows(); //獲取sheet頁籤的總行數
//獲取sheet表中所包含的總行數
/******************設定字型樣式***************************/
WritableFont font = new WritableFont(WritableFont.createFont("宋體"),10,WritableFont.NO_BOLD);
WritableCellFormat wcf = new WritableCellFormat(font);
/****************************************************/
Cell cell = readsheet.getCell(0,rsRows); //獲取sheet頁的單元格
if(cell.getContents().equals("")){
Label labetest1 = new Label(0,rsRows,caseNo); //第一列:用例編號
Label labetest2 = new Label(1,rsRows,testPoint);//第二列:用例標題
Label labetest3 = new Label(2,rsRows,testData); //第三列:測試資料
Label labetest4 = new Label(3,rsRows,preResult);//第四列:預期結果
Label labetest5 = new Label(4,rsRows,fresult); //第五列:實際結果
if(preResult.equals(fresult)){ // 判斷兩個值同時相等才會顯示通過
result = "通過"; //預期結果和實際結果相同,測試通過
wcf.setBackground(Colour.BRIGHT_GREEN); //通過案例標註綠色
}
else{
result = "不通過"; //預期結果和實際結果不相同,測試不通過
wcf.setBackground(Colour.RED); // 不通過案例標註紅色
}
Label labetest6 = new Label(5,rsRows,result,wcf);//第六列:測試結果
readsheet.addCell(labetest1);
readsheet.addCell(labetest2);
readsheet.addCell(labetest3);
readsheet.addCell(labetest4);
readsheet.addCell(labetest5);
readsheet.addCell(labetest6);
}
wbook.write();
wbook.close();
}
/**
* cOutputFile 作用:建立Excel檔案,
* tradeType為檔名稱字首,
* 返回結果:檔案路徑,作為wOutputFile寫入結果檔案的入參
* @throws IOException
* @throws WriteException
* */
public String cOutputFile(String tradeType) throws IOException, WriteException{
String temp_str = "";
Date dt = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
temp_str = sdf.format(dt); //獲取時間戳
// 相對路徑預設為 JMeter_home\bin 目錄
// 以時間戳命名結果檔案,確保唯一
// 生成檔案路徑
String filepath = "D:\\\\"+tradeType+"_output_" + "_" + temp_str + ".xls";
File output = new File(filepath);
if(!output.isFile()){
// 如果指定的檔案不存在,建立新該檔案
output.createNewFile();
// 寫檔案
// 新建一個writeBook,在新建一個sheet
WritableWorkbook writeBook = Workbook.createWorkbook(output);
//命名sheet // createsheet(sheet名稱,第幾個sheet)
WritableSheet sheet = writeBook.createSheet("輸出結果", 0);
//設定首行字型為宋體,11號,加粗
WritableFont headfont = new WritableFont(WritableFont.createFont("宋體"),11,WritableFont.BOLD);
WritableCellFormat headwcf = new WritableCellFormat(headfont);
headwcf.setBackground(Colour.GRAY_25); // 灰色顏色
// 設定列寬度setcolumnview(列號,寬度)
sheet.setColumnView(0, 11); //設定列寬
sheet.setColumnView(1, 20);
sheet.setColumnView(2, 40);
sheet.setColumnView(3, 10);
sheet.setColumnView(4, 10);
sheet.setColumnView(5, 10); //如果需要再新增列,這裡往下新增
headwcf.setAlignment(Alignment.CENTRE); //設定文字居中對齊方式;//文字居中
headwcf.setVerticalAlignment(VerticalAlignment.CENTRE); // 設定垂直居中;
Label labe00 = new Label(0,0,"用例編號",headwcf); //寫入內容:Label(列號,行號,內容)
Label labe10 = new Label(1,0,"用例標題",headwcf);
Label labe20 = new Label(2,0,"測試資料",headwcf);
Label labe30 = new Label(3,0,"預期結果",headwcf);
Label labe40 = new Label(4,0,"實際結果",headwcf);
Label labe50 = new Label(5,0,"執行結果",headwcf); //往下新增
sheet.addCell(labe00);
sheet.addCell(labe10);
sheet.addCell(labe20);
sheet.addCell(labe30);
sheet.addCell(labe40);
sheet.addCell(labe50);//往下新增
writeBook.write();
writeBook.close();
}
return filepath;
}
}
提示:
- 使用自己的IDE開發工具,把該檔案生成JAR檔案。
- 在編寫Java程式碼的時候,別忘記把
jxl.jar
匯入到專案中,因為是對jxl.jar
中的功能進行的封裝。- 我使用的是IDEA編輯Java程式碼,建立的Maven專案,在
src/main/java
目錄下直接建立該檔案即可。如果你自己增加了Package,也就是多增加了路徑,在下面引用程式碼的時候,就會變得麻煩。需要導包操作,或者呼叫的時候增加路徑。- 上面定義生成的Excel檔案在D盤根目錄,如需生成到其他位置,在程式碼中修改。
- 關於生成Excel檔案內容的格式,可以自定義修改。
當然,你也可以不封裝上面的程式碼,把上面的程式碼直接寫在BeanShell取樣器指令碼中也是一樣的。(有Java基礎你會明白的)
2、準備測試需要的資料
程式碼準備好後,我們要準備對應的測試資料,需要準備的資料有兩部分:
- 測試用例資料。
- 引數化資料。
說明:我們都用
.csv
格式的資料檔案,注意編碼UTF-8,防止中文亂碼。
(1)測試用例資料
測試用例資料檔案內容如下:
(2)引數化資料
引數化資料檔案內容如下:
提示:測試用例資料和引數化資料可以準備到一個檔案中,也可以分開準備,根據自己的需求去做。
3、測試結果寫入Excel演示
(1)測試計劃內包含的元件
新增元件操作步驟:
- 建立測試計劃。
- 建立執行緒組:
選中“測試計劃”右鍵 —> 新增 —> 執行緒(使用者) —> 執行緒組
。 - 線上程組中,新增配置元件
CSV Data Set Config
元件:選中“執行緒組”右鍵 —> 新增 —> 配置元件 —> CSV Data Set Config
。 - 線上程組中,新增取樣器“HTTP請求”元件:
選中“執行緒組”右鍵 —> 新增 —> 取樣器 —> HTTP請求
。 - 在取樣器下,新增後置處理器“正規表示式提取器”元件:
選中“取樣器”右鍵 —> 新增 —> 後置處理器 —> 正規表示式提取器
。 - 線上程組中,新增邏輯控制器“僅一次控制器”元件:
選中“執行緒組”右鍵 —> 新增 —> 邏輯控制器 —> 僅一次控制器
。 - 線上程組中,新增取樣器“BeanShell 取樣器”元件:
選中“執行緒組”右鍵 —> 新增 —> 取樣器 —> BeanShell取樣器
。 - 線上程組中,新增監聽器“察看結果樹”元件:
選中“執行緒組”右鍵 —> 新增 —> 監聽器 —> 察看結果樹
。
提示:需要重複新增的元件這裡不重複描述。
最終測試計劃中的元件如下:
點選執行按鈕,會提示你先儲存該指令碼,指令碼儲存完成後會直接自動執行該指令碼。
(2)CSV資料檔案設定介面內容
我們需要新增兩個CSV Data Set Config
元件,一個用於讀取測試用例的資料檔案,另一個用於讀取測試資料的引數化檔案。
讀取測試用例資料的CSV元件:
讀取測試資料引數化檔案的CSV元件:
提示:要檢視好資料檔案中是否有標題行,是否有中文,資料是否帶引號,進行相應的配置。如果不明白請看前面的引數化文章,寫的很詳細。
(3)登陸介面請求內容
標準的POST請求,填寫好請求的基本要素,和需要的引數。
如下圖所示:
(4)正規表示式提取器內容
使用正規表示式提取器,將每一次請求返回的資料,提取出來,用於後面的操作。
並且正規表示式提取器是放在登陸請求的下一級。
如下圖所示,提取返回的全部內容,賦值給fresult
變數。
(5)BeanShell取樣器(建立Excel)
建立一個BeanShell取樣器請求,用於建立Excel檔案。
因為登陸操作有多條用例,但不需要建立多個Excel檔案,我們就需要使用一個邏輯控制器,來控制該BeanShell請求只執行一次。
把此BeanShell取樣器請求放在僅一次控制器的下一級,使該取樣器整個迴圈過程中只會執行一次,也就是隻會生成一個Excel檔案。
如下圖所示:
然後在指令碼中,寫入BeanShell程式碼:
// 1.新建物件
t = new CWOutputExcelFile();
// 2.新建excel檔案
String filepath = t.cOutputFile("測試");
// 3.將excel檔案路徑儲存為jmeter變數,方便後期使用。
vars.put("filepath",filepath);
BeanShell取樣器介面內容介紹:
-
Reset bsh.Interpreter before each call
:每個BeanShell測試元素都有自己的直譯器副本(對於每個執行緒)。如果重複呼叫測試元素,例如在迴圈內,除非選擇在每次呼叫之前重置bsh.Interpreter
選項,否則直譯器將保留在呼叫之間。一些長時間執行的測試可能會導致直譯器使用大量記憶體。
由於BeanShell的bsh.Interpreter
存在記憶體洩露,常規方法無法支援長時間的壓力測試。JMeter官網推薦,在使用BeanShell進行長時間測試時,開啟選項Reset bsh.Interpreterbefore each call
,則在每次呼叫BeanShell程式前,都把直譯器重置,以釋放直譯器之前佔用的記憶體。 -
引數 (-> String Parameters和String[]bsh.args)
:輸入String引數。String []bsh.args
是主類main函式的形式引數,是一個String 物件陣列,可以用來獲取命令列使用者輸入進去的引數。 -
指令碼檔案:指令碼檔案(可以填入指令碼檔案路徑),可以點選後邊的瀏覽選擇指令碼檔案。
-
Script (see below for variables that are defined)
:編寫指令碼,參照下文定義的變數(使指令碼檔案參照定義的變數來執行)
(6)BeanShell取樣器(寫回結果)
把每次請求介面返回的結果,寫入到Excel檔案中。因為每次迴圈都要執行,所以放在和登陸請求同級。
介面內容如下圖所示:
編寫指令碼內容如下:
// 1.建立寫回結果的物件
s = new CWOutputExcelFile();
// 2.引數準備
// (1)拼接成json格式的測試資料
String testData="{"+"\"mobilephone\":\""+"${mobilephone}\","+"\"pwd\":\""+"${pwd}\""+"}";
//用get方法可以確保獲取到的是字串,裡面傳遞的是變數名,不需要用${變數名}這種方式咯!
// (2)獲取預期結果
// 獲取引數化檔案中的變數,返回值為字串型別,否則直接引用為json型別
String preResult = vars.get("preResult");
// (3)獲取返回結果
// 獲取正規表示式中的結果檔案,返回值為字串型別,否則直接引用為json型別
String fresult = vars.get("fresult");
// 3.寫測試結果到excel檔案,呼叫方法wOutputFile方法
s.wOutputFile("${filepath}","${caseNo}","${testPoint}",testData,preResult,fresult);
提示:在JMeter中我們經常會使用正規表示式去獲取介面返回的引數,在引用引數的時候,可以直接使用
${引數名}
。如果這個引數中不帶有任何需要轉義的符號的時候,那麼這種引用方式就沒有問題,否則JMeter就沒法識別。這時可以用vars.get("引數名")
的方式,將JMeter變數先變成Java變數,然後再去操作,就不會報錯了。
(7)執行緒組介面內容
因為我們有4個用例,所以迴圈數填寫4。(不要修改執行緒數)
提示:執行緒數和迴圈次數的區別
僅一次控制器,對某個執行緒組只執行一次。
- 如果修改執行緒數,如10 ,就是開啟是10個執行緒跑這個執行緒組,所以僅一次控制器中的內容執行10次。
- 如果修改迴圈次數,如10 ,表示只開啟一個執行緒,跑這個執行緒組10次,而這10次中僅執行一次僅一次控制器中的內容。
(8)執行檢視結果
執行指令碼檢視結果,我們可以看到建立了一次Excel檔案,執行了4次登陸操作,也寫了四次內容到Excel中。這和我們預習的流程是一樣的。
如下圖所示:
然後我們再來看看Excel檔案中的內容,如下圖所示:
我們可以根據自己的需求,自定義檔案中的格式和需要儲存的內容(修改封裝程式碼)。