軟件測試攻略(二十四):界面自動化之testNG&Java封裝

一、testNG

TestNG是Java中的一個測試框架。Java中已經(jīng)有一個JUnit的測試框架了。 TestNG比JUnit功能強(qiáng)大的多。 測試人員一般用TestNG來寫自動化測試。 開發(fā)人員一般用JUnit寫單元測試。
上一篇已經(jīng)提過,我們在pom.xml里面添加了testNG的依賴


image.png

二、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**

image.png

但是執(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)如下:
image.png

image.png

將testNG.xml拖到包下面。


image.png

testNG.xml右鍵,run as -> testNG Suit


image.png

觀察執(zhí)行結(jié)果:
image.png

三、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ù)化方式

  1. Parameters
  • 在testNG.xml里面配置參數(shù)化數(shù)據(jù)
<parameter name="userName" value="guoya"></parameter> 
<parameter name="password" value="Aa123!"></parameter> 
image.png

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);
    }
}
  1. 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ù)


image.png

保存為csv文件,

    @DataProvider(name="dataLogin")
    public static Object[ ][ ] dataLogin() {
        Object[ ][ ] obData = CSVReader.readCSV("E:/softwareData/dataLogin.csv");
        return obData;
    
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 感謝原作者的奉獻(xiàn),原作者博客地址:http://blog.csdn.net/zhu_ai_xin_520/arti...
    狼孩閱讀 14,108評論 1 35
  • 本文首發(fā)于 https://jaychen.cc作者 jaychen 寫一篇小文,介紹一下 Java 下單元測試工...
    jaychenIsUsed閱讀 1,921評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,868評論 18 139
  • 文/十二月墨 一座陌生的城市,不知該往哪走! 一顆千瘡百孔的心,只是想找個陌生的環(huán)境讓它安靜而已! 愛情,曾經(jīng)讓我...
    十二月墨閱讀 421評論 0 3
  • 清晨六點(diǎn),像冬眠的小獸感知到春之溫煦般,沉睡的意識自然覺醒,像黑夜里悄然亮起的一盞燈;緊接著,像是暫停的音樂重新播...
    M夢兮閱讀 423評論 2 7