一、testNG
TestNG是Java中的一個測試框架。Java中已經(jīng)有一個JUnit的測試框架了。 TestNG比JUnit功能強(qiáng)大的多。 測試人員一般用TestNG來寫自動化測試。 開發(fā)人員一般用JUnit寫單元測試。
上一篇已經(jīng)提過,我們在pom.xml里面添加了testNG的依賴
二、testNG注解:
@BeforeSuite
被@BeforeSuite注解的方法,將會在testng定義的xml根元素里面的所有執(zhí)行之前運(yùn)行
@AfterSuite
被@AfterSuite注解的方法,將會在testng定義的xml根元素里面的所有執(zhí)行之后運(yùn)行。
@BeforeTest
被@BeforeTest注解的方法,將會在一個元素定義的所有里面所有測試方法執(zhí)行之前運(yùn)行。
@AfterTest
被@AfterTest注解的方法,將會在一個元素定義的所有里面所有的測試方法執(zhí)行之后運(yùn)行。
@BeforeClass
被@BeforeClass注解的方法,將會在當(dāng)前測試類的第一個測試方法執(zhí)行之前運(yùn)行。
@AfterClass
被@AfterClass注解的方法,將會在當(dāng)前測試類的最后一個測試方法執(zhí)行之后運(yùn)行。
@BeforeMethod
被@BeforeMethod注解的方法,將會在當(dāng)前測試類的每一個測試方法執(zhí)行之前運(yùn)行。
@AfterMethod
被@AfterMethod注解的方法,將會在當(dāng)前測試類的每一個測試方法執(zhí)行之后運(yùn)行
@Test 注解
@Test 注解是TestNG的核心注解,被打上該注解的方法,表示為一個測試方法
暫時我們先主要記住:
- @BeforeClass
被@BeforeClass注解的方法,將會在當(dāng)前測試類的第一個測試方法執(zhí)行之前運(yùn)行。 - @AfterClass
被@AfterClass注解的方法,將會在當(dāng)前測試類的最后一個測試方法執(zhí)行之后運(yùn)行。 - @Test 注解
@Test 注解是TestNG的核心注解,被打上該注解的方法,表示為一個測試方法
二、如何使用testNG
我們給設(shè)置環(huán)境變量、打開瀏覽器這個方法,添加注解@BeforeClass,表示在第一個測試方法執(zhí)行之前運(yùn)行。給關(guān)閉瀏覽器這個方法添加注解@AfterClass,表示在最后一個測試方法執(zhí)行之后運(yùn)行。
@BeforeClass
public void startUp() {
//設(shè)置環(huán)境變量,指定chromedriver的路徑
System.setProperty("webdriver.chrome.driver",
"src/main/resources/driver_2_38_v65-67/chromedriver.exe");
//設(shè)置瀏覽器的參數(shù)
ChromeOptions options = new ChromeOptions();
//最大化瀏覽器
options.addArguments("--test-type", "--start-maximized");
//打開瀏覽器
driver = new ChromeDriver();
}
@AfterClass
public void shutDown(){
//關(guān)閉瀏覽器
driver.close();
//關(guān)閉瀏覽器驅(qū)動
driver.quit();
}
@Test
public void openUrl(){
//打開要測的登錄頁面
driver.get("http://www.guoyasoft.com:8080/guoya-client");
}
@Test
//登錄
public void login() {
//定位用戶名框
WebElement userName= driver.findElement(By.id("userName"));
userName.clear();
//輸入用戶名
userName.sendKeys("wuling");
//定位密碼框
WebElement password= driver.findElement(By.id("password"));
password.clear();
//輸入密碼
password.sendKeys("0000");
//定位并點(diǎn)擊登錄
driver.findElement(By.id("loginBtn")).click();
}
給我們要測試的方法添加@test注解,上述代碼給打開網(wǎng)頁方法和登錄方法添加@test注解
如何使用:
在給方法添加testNG注解后,直接右鍵類run as -> testNG test**
但是執(zhí)行@test的順序是怎樣的呢?
1、按照字母表順序執(zhí)行測試方法
如果需要測試的方法只有@Test,那么它將通過方法名的首字母按照字母表順序執(zhí)行
2、給方法添加priority屬性
根據(jù)業(yè)務(wù)邏輯,給各個方法添加priority屬性,按照@Test(priority = 0)——>@Test(priority = 1)——>……@Test(priority = N)執(zhí)行。
3、在testNG.xml配置順序(推薦)
testNG.xml的基本結(jié)構(gòu)如下:
將testNG.xml拖到包下面。
testNG.xml右鍵,run as -> testNG Suit
觀察執(zhí)行結(jié)果:
三、Java封裝
實(shí)際的工作中,我們避免在業(yè)務(wù)流有過多的代碼干擾,我們的業(yè)務(wù)操作,基本是定位元素-操作元素,比如輸入用戶名、密碼、校驗(yàn)碼的基本套路都是,定位文本框-清除文本框-向輸入文本內(nèi)容,那我們是否可以把這個套路封裝成一個方法,需要用時,只用填幾個參數(shù),而節(jié)省空間去寫幾行代碼。
//定位用戶名框
WebElement userName= driver.findElement(By.id("userName"));
//清除
userName.clear();
//輸入用戶名
userName.sendKeys("wuling");
將他封裝成一個方法,
public void textInput(String xp,String texts) {
WebElement textInp= driver.findElement(By.xpath(xp));
textInp.clear();
textInp.sendKeys(texts);
}
當(dāng)我們需要操作文本框時,只要調(diào)用這個方法,并且寫入文本框的地址,和要輸入的內(nèi)容作為參數(shù)即可。
textInput("http://input[@id=userName]","wuling");
原本的三行代碼,寫成一行即可。
我們新建一個class文件來專門寫工具流,用一個專門寫業(yè)務(wù)流,這樣代碼更清晰明了。而且,工具流以后可以重復(fù)使用。業(yè)務(wù)邏輯更改,直接更改業(yè)務(wù)流即可,提高效率。
我們將工具流新建為AutoBasic.class,
public class AutoBasic {
public WebDriver driver; //將driver設(shè)置為全局變量
//啟動瀏覽器
public void startUp() {
//設(shè)置環(huán)境變量,指定chromedriver的路徑
System.setProperty("webdriver.chrome.driver",
"src/main/resources/driver_2_38_v65-67/chromedriver.exe");
//設(shè)置瀏覽器的參數(shù)
ChromeOptions options = new ChromeOptions();
//最大化瀏覽器
options.addArguments("--test-type", "--start-maximized");
//打開瀏覽器
driver = new ChromeDriver(options);
sleep() ;
}
//關(guān)閉瀏覽器
public void shutDown(){
//關(guān)閉瀏覽器
sleep() ;
driver.close();
//關(guān)閉瀏覽器驅(qū)動
driver.quit();
}
public void sleep() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void openUrl(String url){
//打開要測的登錄頁面
driver.get(url);
sleep();
}
//input文本
public void textInput(String xp,String texts) {
WebElement textInp= driver.findElement(By.xpath(xp));
textInp.clear();
textInp.sendKeys(texts);
sleep();
}
//點(diǎn)擊按鈕
public void buttonInput(String xp) {
WebElement buttonInp= driver.findElement(By.xpath(xp));
buttonInp.click();
}
//下拉框
public void selectFunction(String xp, int i) {
Select select =new Select(driver.findElement(By.xpath(xp)));
select.selectByIndex(i);
}
//刷新
public void navRefresh() {
driver.navigate().refresh();
sleep();
}
新建一個class文件是業(yè)務(wù)流,SearchAuto.java
public class SearchAuto {
AutoBasic fz =new AutoBasic();//要使用AutoBasic.class的方法,先要實(shí)例化
//打開瀏覽器
@BeforeClass
public void startUp() {
fz.startUp();
}
@AfterClass
public void shutDown() {
fz.shutDown();
}
//打開網(wǎng)頁
@Test
public void openUrl() {
fz.openUrl("http://47.98.226.232:8080/guoya-medium/jsp/user/login.jsp");
}
@Test
//登錄
public void login() {
//輸入用戶名
fz.textInput("http://input[@id=\"userName\"]","guoya");
//輸入密碼
fz.textInput("http://input[@id=\"password\"]","Aa123!");
//輸入驗(yàn)證碼
fz.textInput("http://input[@id=\"checkCode\"]","12345");
// 點(diǎn)擊登錄
fz.buttonInput("http://input[@id=\"loginBtn\"]");
}
@Test
//查詢
public void searchUN() {
fz.textInput("http://input[@name=\"userName\"]","guoya");
//點(diǎn)擊查詢
fz.buttonInput("http://tr[2]/td[8]/input");
}
@Test
public void navRefresh() {
fz.navRefresh();
}
@Test
public void searchEdu() {
fz.selectFunction("http://tr[1]/td[6]/select", 2);
fz.buttonInput("http://tr[2]/td[8]/input");
}
可以看到,按照業(yè)務(wù)邏輯,使用工具流里的方法,簡單清晰不迷糊。
四、java封裝_參數(shù)化
public void login() {
fz.textInput("http://input[@id=\"userName\"]","guoya");
fz.textInput("http://input[@id=\"password\"]","Aa123!");
fz.textInput("http://input[@id=\"checkCode\"]","12345");
fz.buttonInput("http://input[@id=\"loginBtn\"]");
}
我們可以進(jìn)一步講這套代碼封裝,將可能需要更改的數(shù)據(jù)寫成參數(shù)
public void login(String um,String pwd) {
fz.textInput("http://input[@id=\"userName\"]",um);
fz.textInput("http://input[@id=\"password\"]",pwd);
fz.textInput("http://input[@id=\"checkCode\"]","12345");
fz.buttonInput("http://input[@id=\"loginBtn\"]");
}
這樣我們完成整個登錄,就只需要寫:
login("guoya","Aa123!");
五、testNG參數(shù)化及斷言
(一)斷言
在Jmeter里我們已經(jīng)了解過斷言,它相當(dāng)于預(yù)期結(jié)果,一條測試用例,除了測試步驟,測試數(shù)據(jù),必須要有斷言,與Jmeter相同的,如果不設(shè)置斷言,如果不設(shè)置判斷,那自動化沒有意義。
語句:
Assert.assertEquals(result, true);
result是實(shí)際結(jié)果和true為預(yù)期結(jié)果,實(shí)際結(jié)果與預(yù)期結(jié)果做比較,一般用Boolean值做斷言數(shù)據(jù)。
在工具流AutoBasic.java寫入一個新的方法,得到實(shí)際的結(jié)果,返回一個boolean值。
public boolean assertPage(String s) {
boolean result=driver.getPageSource().contains(s);
return result;
}
@test
//登錄成功測試用例
public void loginSuccess(String um, String pwd){
//打開網(wǎng)頁
openUrl();
//登錄
login("guoya","Aa123!");
//實(shí)際結(jié)果,如果登錄成功跳轉(zhuǎn)到查詢頁面,故以“查詢”來做斷言,
//如果登錄成功,應(yīng)該返回true,如果登錄不成功,應(yīng)該返回false
boolean result1=fz.assertPage("查詢");
//實(shí)際結(jié)果與預(yù)期結(jié)果比較
Assert.assertEquals(result1, true);
}
(二)參數(shù)化
testNG有兩種參數(shù)化方式
- Parameters
- 在testNG.xml里面配置參數(shù)化數(shù)據(jù)
<parameter name="userName" value="guoya"></parameter>
<parameter name="password" value="Aa123!"></parameter>
name后面是變量名,value后面是變量值,成對,即
userName="guoya"
password="Aa123!"
- 那如何使用呢
@Parameters({"userName","password"})
public void loginSuccess( String um, String pwd){
openUrl();
login(um,pwd);
boolean result1=fz.assertPage("查詢");
Assert.assertEquals(result1, true);
將原本的@test改為@Parameters({"userName","password"})即可。
代碼進(jìn)一步可以修改為
@Parameters({"userName","password"})
public void loginSuccess( String um, String pwd, String exp1){
//exp1就是斷言,用斷言結(jié)果與true做比較,
//如果斷言結(jié)果為true,exp結(jié)果為true,如果斷言結(jié)果為false,exp結(jié)果為false
boolean exp=exp1.equals("true");
openUrl();
login(um,pwd);
boolean result1=fz.assertPage("查詢");
if(result1){
Assert.assertEquals(result1, exp);
}else{
Assert.assertEquals(result1, exp);
}
}
- dataprovider
步驟
(1)使用@Test(dataProvider="sdata")給測試方法添加注解使用參數(shù)化的數(shù)據(jù);
(2)需要自己寫一個方法來存儲數(shù)據(jù)
方法1:二維數(shù)組存數(shù)據(jù)
@DataProvider(name="dataLogin")
public Object[][] dataLogin() {
Object[][] ob = new Object[4][3];//一組數(shù)據(jù)組成一條測試用例
//一條測試用例
//測試數(shù)據(jù)
ob[0][0]="wuling";
ob[0][1]="0000";
//斷言
ob[0][2]="true";
//一條測試用例
ob[1][0]="wuling1";
ob[1][1]="0000";
ob[1][2]="false";
//一條測試用例
ob[2][0]="wuling";
ob[2][1]="0001";
ob[2][2]="false";
//一條測試用例
ob[3][0]="wuling12";
ob[3][1]="0022";
ob[3][2]="false";
return ob;
}
方法2:csv文件存數(shù)據(jù)
保存為csv文件,
@DataProvider(name="dataLogin")
public static Object[ ][ ] dataLogin() {
Object[ ][ ] obData = CSVReader.readCSV("E:/softwareData/dataLogin.csv");
return obData;
}