TestNG 測試框架-尚學堂

2020-08-11 22:31:22

第七章 TestNG 測試框架

一、 什麼是測試框架
自動化測試框架是由一個或多個自動化測試基礎模組、自動化測試管理模組、自動
化測試統計模組等組成的工具集合。
二、 搭建 TestNG 框架環境
1 什麼是 TestNG
是一個開源自動化測試框架,TestNG 表示下一代。
用於設定測試前的準備程式碼,測試程式碼,測試完畢後的處理程式碼。
2 安裝 testng-6.14.zip
離線安裝
(先斷網)幫助→安裝新軟體→新增,位置選擇 achive,選擇 zip 檔案即可。
網路安裝
幫 助 → 安 裝 新 軟 件 → 聯 網 安 裝 testing Work with 下 輸 入 :
http://beust.com/eclipse→新增→勾選 TestNG
三、 使用 TestNG 中註解進行測試
1 什麼是註解
表示「在某些階段必然被呼叫的程式碼」;
下面 下麪的註解一般用於修飾測試方法,測試方法名隨意。
2 常用註解
2.1 @BeforeClass 註解
在呼叫當前類的第一個測試方法之前執行。
@BeforeClass
public void setup() throws Exception {
System.setProperty("webdriver.ie.driver", "C:\\...\\IEDriverServer.exe");
driver= new InternetExplorerDriver();
driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);
}2.2 @AfterClass 註解
在呼叫當前類的最後一個測試方法之後執行。
@AfterClass
public void tearDown() throws Exception {
driver.quit();
}
2.3 @BeforeMethod 註解
在每個測試方法之前執行。
2.4 @AfterMethod 註解
在每個測試方法之後執行。
2.5 @Test(屬性 1=1,屬性 2=2...)註解
用於修飾測試方法,表示要對被測試類的某個或某些方法進行測試。
屬性
description="測試描述"
priority=優先順序(從 0 開始)
enabled=falsefalse 表示忽略測試)
timeOut=?ms(限時測試,一旦測試的內容執行超過了該時間長度,那麼將會
終止,同時標記爲 failed
dataProvider="Dataprovider 的名稱或方法名"
dataProviderClass=產生測試數據的類
2.6 @DataProvider(name="參數集名")註解
用於修飾獲得參數的方法。
此方法用於生成測試數據。
@Listeners({TestReport.class})
//監聽測試報告類
3 斷言
用來斷定程式中是否存在缺陷。
3.1 Assert.assertTrue(boolean 型結果)
寫法類似於正則表達式,使用更方便。
Boolean rs=driver.findElement(By.tagName("body")).getText().contains("Welcome
to the Web Tours site");
Assert.assertTrue(rs);3.2 Assert.assertEquals(實際結果,預期結果)
用於測試期望結果的斷言,即測試兩個物件是否相等。
String actual=driver.getTitle();
String expected="Web Tours";
Assert.assertEquals(actual, expected);
4 參數化
4.1 @DataProvider(name="測試數據集名")註解
name 項可省略,括號無所謂
4.2 建立獲取參數的方法
@DataProvider
public Object[][] getParam() throws Exception{
Object data[][]={ {"London","Paris"},{"Denver","London"},{"Paris","Denver"} };
return data;
}
4.3 使用 dataProvider 存取參數
@Test(description="訂票",priority=2,dataProvider="getParam")
public void book(String cong , String dao){
new Select(drv.findElement(By.name("depart"))).selectByVisibleText(cong);
new Select(drv.findElement(By.name("arrive"))).selectByVisibleText(dao);
Boolean
rs=drv.findElement(By.tagName("body")).getText().contains("leaves
"+cong+" for "+dao);
assertTrue(rs);
drv.findElement(By.name("Book Another")).click();
}
4.4 不使用列表獲取檔案中的參數
@DataProvider
public Object[][] getParam() throws Exception{
File file=new File("C:\\...\\flights.txt");
//開啓檔案,計算檔案行數
FileReader bytes=new FileReader(file);
BufferedReader chars=new BufferedReader(bytes);
String row=null;
int lineCount=0;
while((row=chars.readLine())!=null)lineCount++;
chars.close();
//重新開啓檔案,讀取每行
bytes=new FileReader(file);
chars=new BufferedReader(bytes);
Object[][] data=new Object[lineCount][];
int i=0;
while((row=chars.readLine())!=null){
String cols[]=row.split("\t");
data[i++]=cols;
}
//測試檢視每行
/*
for(Object x[]:data){
for(Object y:x)
System.out.print(y+" ");
System.out.println();
}
*/
chars.close();
return data;
}
4.5 分離獲得參數的類
定義獲得參數的類
public class Param{
@DataProvider(name=?)
public Object[][] getParam() throws Exception{
...
}
}
參照參數類中的參數
@Test(description="訂票",priority=2,dataProvider="getParam",dataProviderClass=
加引號的其他類名.class
public void book(String cong , String dao){
new Select(drv.findElement(By.name("depart"))).selectByVisibleText(cong);
new Select(drv.findElement(By.name("arrive"))).selectByVisibleText(dao);
Boolean
rs=drv.findElement(By.tagName("body")).getText().contains("leaves
"+cong+" for "+dao);
assertTrue(rs);
drv.findElement(By.name("Book Another")).click();
}4.6 使用列表獲取檔案中的參數
@DataProvider
public Object[][] getParam() throws Exception{
List<String[]> rows=new ArrayList<String[]>();
File file=new File("C:/.../flights.txt");
FileReader reader=new FileReader(file);
BufferedReader buffer=new BufferedReader(reader);
String row=null;
while((row=buffer.readLine())!=null){
String columns[]=row.split("\t");
rows.add(columns);
}
reader.close();
Object[][] data=new Object[rows.size()][];
for(int i=0;i<rows.size();i++)
data[i]=rows.get(i);
return data;
}
5 生成測試報告
測試報告預設儲存位置
Java 專案名\test-output
可以自己編寫並優化 TestReport.java
測試類中新增監聽器@Listeners({TestReport.class})即可
class 是固定關鍵字
放到測試類名的上一行
@Listeners({TestReport.class})
//監聽測試報告類
public class WebTest {
...
}
6 測試套件
6.1 測試 test
一個 test 可以包含一系列的測試方法,測試方法由@Test 註解。
6.2 測試套件 suite
一個 suite 可以包含多個獨立的 test6.3 定義測試套件
首先定義多個測試類,可以在同一個包中,也可以在不同包中。
右擊 Java 專案→TestNg→Convert to TestNG
Suite 命名
爲測試命名
Class selection
Classes
使用類名錶示一個測試
包中的類可以寫成「包名.類名」
Parallel mode
tests
表示並行執行測試
Thread count
用於設定並行執行緒數量
必須與 Parallel mode 同時使用
一般設定爲並行測試的數量
6.4 修正 testng.xml
<suite thread-count="2" name="測試套件名稱" annotations="JDK" parallel="tests">
<test name="自定義測試名 1">
<classes>
<class name="測試類 1 的名字"/>
</classes>
</test>
<test name="自定義測試名 2">
<classes>
<class name="測試類 2 的名字"/>
</classes>
</test>
</suite>
首先定義多個測試類,可以自同一個包中,也可以在不同包中。
annotations 表示註解
不能省略
JDK 必須大寫
6.5 執行測試套件
開啓 testng.xml→點選工具列執行按鈕→選擇「TestNG Suite」。7 爲測試方法傳遞參數
7.1 定義參數
修改 testng.xml
<suite>
<parameter name="參數名" value="參數值" />
<test name="測試名">
<parameter name="參數名" value="參數值" />
<classes>
<class name="測試類的名字"/>
</classes>
</test>
</suite>
Suite 範圍內定義某個參數的值,對所有的 Test 都有效。
Test 範圍內定義某個參數的值,只是針對該 Test 有效。
如果同時在 Suite Test 中定義某個參數,Test 範圍的值會遮蔽 Suite 的值。
這種方式的參數值必須直接指定,不如 DataProvider 靈活。
7.2 參照參數
@Test
@Parameters({ "參數名 1", "參數名 2" })
public void 測試方法(String 參數名 1){
}
四、 執行 Excel 測試用例
1 準備 Excel 測試用例
至少包括輸入數據和預期結果。
2 Excel
首先匯入 jxl.jar
Excel 的程式碼
InputStream file=new FileInputStream("e:\\cases.xls");
//建立輸入流
Workbook excel=Workbook.getWorkbook(file);
//獲取 Excel 檔案物件
Sheet sheet=excel.getSheet(0);
//獲取檔案的指定工作表,預設第一個
List<String[]> list=new ArrayList<String[]>();
Cell cell=null;
//單元格
for (int i=0; i<sheet.getRows();i++) { //0 表示第 1
String[] rowi_col=new String[sheet.getColumns()]; //建立陣列儲存一行的多列值for (int j= 0;j<sheet.getColumns();j++) {
cell=sheet.getCell(j,i);
//獲取第 i 行第 j 列的值
rowi_col[j]=cell.getContents();
}
list.add(rowi_col);// 把剛獲取的列存入 list
}
file.close();
3 返回 Object 物件作爲參數
Object[][] data=new Object[list.size()][];
for(int i=0;i<list.size();i++)
data[i]=list.get(i);
4 斷言失敗時輸出實際結果
斷言失敗時,斷言語句後面的語句將停止執行。
String result=driver.findElement(By.tagName("body")).getText();
Boolean loginResult=result.contains(expect);
try{
Assert.assertTrue(loginResult);
}catch(AssertionError e){
Assert.fail(result);
}
五、 存取數據庫
1 匯入相關數據庫的包
網上下載對應數據庫的.jar
Eclipse 中的操作
JAR 系統庫→構建路徑→設定構建路徑→新增外部 JAR
2 載入數據庫驅動包
Class.forName("數據庫驅動類名");
返回類,作用是載入要連線的數據庫的驅動到 JVMJava 虛擬機器)。
成功載入後,會將 Driver 類的範例註冊到 DriverManager 類中。
mysql 數據庫驅動類名
com.mysql.jdbc.Driver
3 連線數據庫
Connection conn=DriverManager.getConnection ("jdbc:DBMS 型別://地址:埠號/數據庫名", "使用者名稱", "密碼");
Connection 是一個介面;
DriverManager 是一個類,用於通過驅動程式連線數據庫;
getConnection 方法返回 Connection 介面。
4 執行 SQL 語句
數據查詢
預編譯形式的 SQL 語句
數據庫可以把編譯後的執行程式碼快取在記憶體中,當再次執行相同的 SQL
語句時就不需要重新編譯了,只要將參數直接傳入編譯過的語句執行程式碼
中就會得到執行。
預編譯可以提高數據庫效能,還可以防範 SQL 注入。
String sql="select ... where 列名 1=? and 列名 2=?";
?是固定寫法
PreparedStatement state=conn.prepareStatement(sql);
state.setString(1,值 1);
1 表示第 1 個參數,值是參數值,依次類推
獲得結果集
ResultSet rs=state.executeQuery( );
只能執行查詢操作,返回一個結果集,不能用於增刪改。
ResultSet 是一個介面,用於暫存結果集,但無法獲得行數。
移動行指針,讀取一行數據
rs.next( )
指針移至下一行,成功返回 true,初始位置在第一行之前。
獲得列值
rs.getString(列號或列名)/getDate/getByte/getShort/getInt/getLong/getFloat
列號從 1 開始
列名用雙引號括起來
使用此句之前需先用 rs.next( )讀取一行
結果集已耗盡
原因是 rs 中沒有數據
增刪改
int n=state.executeUpdate(String sql)
執行增刪改操作,返回影響的行數。
5 批次插入多行數據
for( ){
state.setString(1,...);
state.setString(2,...);
...
state.addBatch();
}
state.executeBatch();6 關閉數據庫連線
rs.close( );
state.close( );