软件测试攻略(二十四):界面自动化之testNG&Java封装

一、testNG

TestNG是Java中的一个测试框架。Java中已经有一个JUnit的测试框架了。 TestNG比JUnit功能强大的多。 测试人员一般用TestNG来写自动化测试。 开发人员一般用JUnit写单元测试。
上一篇已经提过,我们在pom.xml里面添加了testNG的依赖


image.png

二、testNG注解:

@BeforeSuite
    被@BeforeSuite注解的方法,将会在testng定义的xml根元素里面的所有执行之前运行
@AfterSuite
    被@AfterSuite注解的方法,将会在testng定义的xml根元素里面的所有执行之后运行。
@BeforeTest
    被@BeforeTest注解的方法,将会在一个元素定义的所有里面所有测试方法执行之前运行。
 @AfterTest
    被@AfterTest注解的方法,将会在一个元素定义的所有里面所有的测试方法执行之后运行。
 @BeforeClass
    被@BeforeClass注解的方法,将会在当前测试类的第一个测试方法执行之前运行。
@AfterClass
    被@AfterClass注解的方法,将会在当前测试类的最后一个测试方法执行之后运行。
@BeforeMethod
    被@BeforeMethod注解的方法,将会在当前测试类的每一个测试方法执行之前运行。
@AfterMethod
    被@AfterMethod注解的方法,将会在当前测试类的每一个测试方法执行之后运行
@Test 注解
    @Test 注解是TestNG的核心注解,被打上该注解的方法,表示为一个测试方法

暂时我们先主要记住:

  • @BeforeClass
    被@BeforeClass注解的方法,将会在当前测试类的第一个测试方法执行之前运行。
  • @AfterClass
    被@AfterClass注解的方法,将会在当前测试类的最后一个测试方法执行之后运行。
  • @Test 注解
    @Test 注解是TestNG的核心注解,被打上该注解的方法,表示为一个测试方法

二、如何使用testNG

我们给设置环境变量、打开浏览器这个方法,添加注解@BeforeClass,表示在第一个测试方法执行之前运行。给关闭浏览器这个方法添加注解@AfterClass,表示在最后一个测试方法执行之后运行。

@BeforeClass
    public void startUp() {
        //设置环境变量,指定chromedriver的路径
        System.setProperty("webdriver.chrome.driver",
                "src/main/resources/driver_2_38_v65-67/chromedriver.exe");
        //设置浏览器的参数
       ChromeOptions options = new ChromeOptions();
        //最大化浏览器
       options.addArguments("--test-type", "--start-maximized");
        //打开浏览器
        driver = new ChromeDriver();
    }
@AfterClass
    public void shutDown(){
        //关闭浏览器
        driver.close();
        //关闭浏览器驱动
        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");
        //定位并点击登录
        driver.findElement(By.id("loginBtn")).click();
    }

给我们要测试的方法添加@test注解,上述代码给打开网页方法和登录方法添加@test注解
如何使用
在给方法添加testNG注解后,直接右键类run as -> testNG test**

image.png

但是执行@test的顺序是怎样的呢?
1、按照字母表顺序执行测试方法
如果需要测试的方法只有@Test,那么它将通过方法名的首字母按照字母表顺序执行
2、给方法添加priority属性
根据业务逻辑,给各个方法添加priority属性,按照@Test(priority = 0)——>@Test(priority = 1)——>……@Test(priority = N)执行。
3、在testNG.xml配置顺序(推荐)
testNG.xml的基本结构如下:
image.png

image.png

将testNG.xml拖到包下面。


image.png

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


image.png

观察执行结果:
image.png

三、Java封装

实际的工作中,我们避免在业务流有过多的代码干扰,我们的业务操作,基本是定位元素-操作元素,比如输入用户名、密码、校验码的基本套路都是,定位文本框-清除文本框-向输入文本内容,那我们是否可以把这个套路封装成一个方法,需要用时,只用填几个参数,而节省空间去写几行代码。

 //定位用户名框
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);
}

当我们需要操作文本框时,只要调用这个方法,并且写入文本框的地址,和要输入的内容作为参数即可。

textInput("//input[@id=userName]","wuling");

原本的三行代码,写成一行即可。
我们新建一个class文件来专门写工具流,用一个专门写业务流,这样代码更清晰明了。而且,工具流以后可以重复使用。业务逻辑更改,直接更改业务流即可,提高效率。
我们将工具流新建为AutoBasic.class,

public class AutoBasic {
    public WebDriver driver; //将driver设置为全局变量
        //启动浏览器
    public void startUp() {
    //设置环境变量,指定chromedriver的路径
        System.setProperty("webdriver.chrome.driver",
                "src/main/resources/driver_2_38_v65-67/chromedriver.exe");
        //设置浏览器的参数
       ChromeOptions options = new ChromeOptions();
        //最大化浏览器
       options.addArguments("--test-type", "--start-maximized");
        //打开浏览器
        driver = new ChromeDriver(options);
        sleep() ;
    }
        //关闭浏览器
    public void shutDown(){
        //关闭浏览器
        sleep() ;
        driver.close();
        //关闭浏览器驱动
                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();
    }
    //点击按钮
    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文件是业务流,SearchAuto.java

public class SearchAuto {
    AutoBasic fz =new AutoBasic();//要使用AutoBasic.class的方法,先要实例化
    //打开浏览器
    @BeforeClass
    public void startUp() {
        fz.startUp();
    }
    @AfterClass
    public void shutDown() {
        fz.shutDown();
    }
    //打开网页
    @Test
    public void openUrl() {
        fz.openUrl("http://47.98.226.232:8080/guoya-medium/jsp/user/login.jsp");
    }
    @Test
  //登录
    public void login() {
    //输入用户名
        fz.textInput("//input[@id=\"userName\"]","guoya");
    //输入密码
        fz.textInput("//input[@id=\"password\"]","Aa123!");
    //输入验证码
        fz.textInput("//input[@id=\"checkCode\"]","12345");
   // 点击登录
        fz.buttonInput("//input[@id=\"loginBtn\"]");
    }
    @Test
    //查询
    public void searchUN() {
        fz.textInput("//input[@name=\"userName\"]","guoya");
    //点击查询
        fz.buttonInput("//tr[2]/td[8]/input");
    }
    @Test
    public void navRefresh() {
        fz.navRefresh();
    }
    @Test
    public void searchEdu() {
        fz.selectFunction("//tr[1]/td[6]/select", 2);
        fz.buttonInput("//tr[2]/td[8]/input");
    }

可以看到,按照业务逻辑,使用工具流里的方法,简单清晰不迷糊。

四、java封装_参数化

public void login() {
        fz.textInput("//input[@id=\"userName\"]","guoya");
        fz.textInput("//input[@id=\"password\"]","Aa123!");
        fz.textInput("//input[@id=\"checkCode\"]","12345");
        fz.buttonInput("//input[@id=\"loginBtn\"]");
}

我们可以进一步讲这套代码封装,将可能需要更改的数据写成参数

public void login(String um,String pwd) {
        fz.textInput("//input[@id=\"userName\"]",um);
        fz.textInput("//input[@id=\"password\"]",pwd);
        fz.textInput("//input[@id=\"checkCode\"]","12345");
        fz.buttonInput("//input[@id=\"loginBtn\"]");
}

这样我们完成整个登录,就只需要写:

login("guoya","Aa123!");

五、testNG参数化及断言

(一)断言
在Jmeter里我们已经了解过断言,它相当于预期结果,一条测试用例,除了测试步骤,测试数据,必须要有断言,与Jmeter相同的,如果不设置断言,如果不设置判断,那自动化没有意义。
语句:
Assert.assertEquals(result, true);
result是实际结果和true为预期结果,实际结果与预期结果做比较,一般用Boolean值做断言数据。
在工具流AutoBasic.java写入一个新的方法,得到实际的结果,返回一个boolean值。

public  boolean assertPage(String s) {
        boolean result=driver.getPageSource().contains(s);
        return result;
    }
@test
//登录成功测试用例
public void loginSuccess(String um, String pwd){
 //打开网页
        openUrl();
//登录
        login("guoya","Aa123!");
//实际结果,如果登录成功跳转到查询页面,故以“查询”来做断言,
//如果登录成功,应该返回true,如果登录不成功,应该返回false
        boolean result1=fz.assertPage("查询");
//实际结果与预期结果比较
        Assert.assertEquals(result1, true);
    }

(二)参数化
testNG有两种参数化方式

  1. Parameters
  • 在testNG.xml里面配置参数化数据
 
 
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"})即可。
代码进一步可以修改为

@Parameters({"userName","password"})
public void loginSuccess( String um, String pwd, String exp1){
 //exp1就是断言,用断言结果与true做比较,
//如果断言结果为true,exp结果为true,如果断言结果为false,exp结果为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")给测试方法添加注解使用参数化的数据;
    (2)需要自己写一个方法来存储数据
    方法1:二维数组存数据
    @DataProvider(name="dataLogin")
    public Object[][] dataLogin() {
        Object[][] ob = new Object[4][3];//一组数据组成一条测试用例
    //一条测试用例
    //测试数据
        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文件存数据


image.png

保存为csv文件,

    @DataProvider(name="dataLogin")
    public static Object[ ][ ] dataLogin() {
        Object[ ][ ] obData = CSVReader.readCSV("E:/softwareData/dataLogin.csv");
        return obData;
    
}

你可能感兴趣的:(软件测试攻略(二十四):界面自动化之testNG&Java封装)