第06课:TestNG

第06课:TestNG 与断言类的使用

引入目的

想必读者学习到这里已经对自动化有了初步的认识,我们回忆下功能测试的流程:

分析需求 → 排测试计划 → 设计测试用例 → 执行测试用例

最终测试工作的落脚点是在测试用例执行完毕上。那么我们对测试系统实现自动化,也应该把偌大的测试系统拆分为一条一条的测试用例,此时 TestNG 就派上用场了。有了一条条的测试用例,我们肯定会拿执行的实际结果与测试用例设计时的期望结果进行比较,执行结果无非是以下两种情况:

  • 当期望结果与实际结果相同,测试用例成功;
  • 当期望结果与实际结果不同,测试用例失败;

为了满足实现上面的判断结果,引入了断言。

TestNG

说明

TestNG 最重要的是注脚 @Test 的使用,一个方法加上 @Test 就表示其是一个测试方法,我们把每一个测试用例封装在不同的 @Test 方法中,那么也就用自动化代码实现了功能测试用例的设计。

注脚对

当然一个完整的测试用例光有 @Test 是远远不够的,TestNG 还提供了其他几组注脚,用来辅助每一个 @Test 的执行,常用的有以下几组:

  • @BeforeClass/@AfterClass

(1)表示的意义:每个测试类运行前和运行后进行执行。

(2)运行次数:每次启动一个测试类,无论其中有多少个测试方法,这对注脚都只执行一次。

(3)应用场景:可以用于启动浏览器和退出浏览器。

  • @BeforeMethod/@ AfterMethod

(1)表示的意义:

@BeforeMethod 在每个 @Test 方法之前会自动被执行;

@AfterMethodz 在每个 @Test 方法之后会自动被执行;

(2)运行次数:这对注脚的运行次数与同一个测试类中包含多少个 @Test 方法有关,如果一个测试类中有 N( N>0 的整数)个 @Test 方法,那么这对注脚就别被执行 N 次。

(3)应用场景:我们知道浏览器是会产生缓存的,所以可以在这对注脚里写清除或者刷新浏览器缓存的代码。

  • 其他注脚

除了上述的两对注脚外,我们还会接触到 @BeforeSuite/@AfterSuite与@BeforeTest/@AfterTest 这两对注脚。但是要注意的是,这两对注脚一般不写在测试类中,而是体现在 TestNG 启动的 XML 文件中。

代码示例

现在将第5篇内容中的 TestCase 类运用 TestNG 中的 @Test 方法进行书写,将其封装成具有两个测试用例的测试类。

  • 第一个测试用例只实现亚马逊网站的首页;
  • 第二个测试用例实现登录功能;

代码如下所示:

package com.test.demo;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.factory.demo.HomePage;
import com.factory.demo.LoginPage;

/**用来测试亚马逊登录界面*/
public class TestLoginCase {
    private WebDriver driver;
    @BeforeClass 
    //启动谷歌浏览器
    public void inialize(){
        System.setProperty("webdriver.chrome.driver", "files\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        System.out.println("打开指定的浏览器驱动");
    }
    @BeforeMethod
    public void beforeMethod(){
        HomePage hp = new HomePage(driver);
        hp.navigateTourl("https://www.amazon.cn/");
        System.out.println("执行初始条件");
    }
    //打开主页并跳转到登录主页
    @Test
    public void urlTOTest(){
        System.out.println("用例一");      
    }
    //录入登录信息
    @Test
    public void loginTest(){
        HomePage hp = new HomePage(driver);
        hp.LogLink();
        LoginPage lp = new LoginPage(driver);
        lp.setPhone("phone");//手机号
        lp.setPassword("password");//密码
        lp.login();
        System.out.println("用例二");
    }
    @AfterMethod
    public void afterMethod(){
        System.out.println("执行后置条件");
    }
    @AfterClass
    public void quit(){
        driver.quit();
        System.out.println("退出浏览器");
    }
}

上述代码在测试类 TestLoginCase 中,设计了两个测试用例。上述用例的执行结果为:

“打开指定的浏览器驱动

执行初始条件

用例二

执行后置条件

执行初始条件

用例一

执行后置条件

退出浏览器

PASSED: loginTest

PASSED: urlTOTest”

从执行结果中可以发现如下三个问题:

  • 用例一和用例二没有按照顺序进行执行;
  • “浏览器启动、退出(注脚 @BeforeClass/@AfterClass)”只执行了一次,“执行初始条件、执行后置条件(@BeforeMethod/@ AfterMethod)”执行了两次,与我们上面说的相符;
  • 本测试类中,没有 main 主函数。基于此下面讲解用 TestNG 设计的测试用例应该如何启动。
@Test 启动

启动方式分为两种,一种是调试时的硬启动,这种方式适用于调试阶段;另一种方式为软启动,通过 XML 文件启动。

  • 硬启动

启动一个测试类中的所有测试方法,选中测试类:

右键 → Debug As → 选择 TestNG test:

启动其中的一个测试方法:

如果我们想只执行 loginTest() 方法,那么就选中它,右键 → Debug As → 选择 TestNG test,此时就不会执行 urlTOTest() 方法。

  • 软启动

硬启动的方式其实质也是软启动,通过读取 XML 文件进行启动,这个 XML 文件在执行时会自动保存在本地的零时文件夹 temp 内。进入到 temp 文件夹下的方式为:

开始菜单 → 输入 %temp% 回车,即进入 temp 的文件夹。

在此文件夹下找到 testng-customsuite.xml 文件,将其复制,直接粘贴到工程下:右键 → Debug As → 选择 TestNG Suite,也可以运行。下面看下 XML 文件的具体内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
  <test verbose="2" name="Default test">
    <classes>
      <class name="com.test.demo.TestLoginCase">
        <methods>
          <include name="urlTOTest"/>
          <include name="loginTest"/>
        </methods>
      </class> <!-- com.test.demo.TestLoginCase -->
    </classes>
  </test> <!-- Default test -->
</suite> <!-- Default suite -->

对上面 XML 文件的说明如下:

  • suite 即是 @BeforeSuite/@AfterSuite
  • test 即是 @BeforeTest/@AfterTest
  • class 即是 @BeforeClass/@AfterClass

我们可以看出 XML 的执行其实就相当于执行测试类中的注脚方法;这里要强调的是:我们以后在执行 TestNG 的时候,推荐大家都采用这种方式启动,优点如下:

(1)可以配置测试用例执行的顺序,上面说过通过硬启动执行的 Test 是无序的,但是通过 XML 执行时,只要按照<include name="XXXX"/>的先后顺序进行配置,那么执行测试用例的时候就会按照这个顺序进行。

(2)更容易直观的看到一个测试类中的 @Test 方法的执行顺序,通过上面的 XML 文件可知执行顺序为:

BeforeSuite → BeforeTest → BeforeClass → BeforeMethod → Test → AfterMethod → AfterClass → AfterTest → AfterSuite

TestNG 的一个重要用途

TestNG 存在的最主要的一个作用是用来与数据驱动结合使用,以控制该脚本是否运行以及运行的次数,还有每次运行时对应的参数.

  • 应用场景

试想下,我们现在是操作一个用户名/密码的登录操作,如果现在想实现多个不同的用户登录的测试用例,难道每一个用户对应一个 case 吗?很显然,这样做是非常愚蠢的,这个时候 TestNG 提供的数据驱动注脚 @DataProvider 就派上了大用途。

  • 代码实现不同用户登录亚马逊

代码如下所示:

//录入登录信息
    @Test(dataProvider="user")
    public void loginTest(String phone,String password){
        HomePage hp = new HomePage(driver);
        hp.LogLink();
        LoginPage lp = new LoginPage(driver);
        lp.setPhone(phone);//手机号
        lp.setPassword(password);//密码
        lp.login();
        System.out.println("用例二");  }
    @DataProvider(name="user")
    public Object[][] dataInfo(){
        return new Object[][]{{"phone1","password1"},{"phone2","password2"}};

    }

对 @DataProvider 的说明如下:

(1)其返回值是一个 Object 类的二维数组,这也就意味着方法中传参的时候可以将参数声明为任意类型的数据,可以为 int、String、float 等等都可以,原因在于 Object 类是 Java 中其他所有类的源父类(自行查看 Java 相关资料)。

(2)@DataProvider 可以指定名称如 @DataProvider(name="user"),这样在测试方法中 @Test(dataProvider="user"),如果没有跟 (name="user"),则测试方法中的 dataProvider 的值就应该为 @DataProvider 注脚的方法名,即为 dataInfo。

TestNG 的优点

现在来总结下使用 TestNG 的优点:

(1)用例可以依据 testng-customsuite.xml 进行执行顺序、个数的优化;

(2)可以通过数据驱动进行多线程测试;

(3)可以不再依靠主方法 Main 进行方法的执行。

断言类

断言类的内容很容易,这里简单介绍一下。首先先明白它的作用,有以下两个方面:

(1)通过获取 UI 上的某个控件对象的某种属性值和期望值进行比较来验证是否正确。

(2)页面跳转后通过验证页面上某个控件对象是否存在,来判断是否缓冲完成。

掌握 Assert 类

Assert 类常用的方法有:

(1)Assert.assertEquals 判断是否相等,Object 类型的对象需要实现 haseCode及equals 方法。

(2)Assert.assertFalse(condition) 判断是否为 false。

(3)Assert.assertNotEquals(actual1, actual2) 判断是否不相等。

(4)Assert.assertNotNull(object) 判断是否不为 null。

(5)Assert.assertNotSame(actual, expected, message) 判断引用地址是否不相同。

(6)Assert.assertNull(object, message) 判断是否为 null。

(7)Assert.assertSame(actual, expected) 判断引用地址是否相同。

(8)Assert.assertTrue(condition) 判断是否为 True。

用法举例
package com.assertion.demo;

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class AssertDemo {
@Test(dataProvider="dataInfo")
public void test2(String info){
    String actual = info;
    String expected ="2";
    System.out.println("测试用例二");
    System.out.println("断言开始");
    Assert.assertEquals(actual, expected,"测试两个字符串的值是否相同");//actual为实际值,expected为期望值
    System.out.println("断言结束");
}
@DataProvider(name="dataInfo")
public Object[][] dataInfo(){
    return new Object[][]{{"1"},{"2"}};

}
}

上述代码的含义是:通过 @DataProvider 向 @Test 依次传入两个值,1、2给 info。通过Assert.assertEquals(actual, expected,"测试两个字符串的值是否相同"来判断 1 和 2 是否相等,2 和 2 是否相等,执行结果如下:

测试用例二

断言开始

测试用例二

断言开始

断言结束

PASSED: test2("2")

FAILED: test2("1")

java.lang.AssertionError: 测试两个字符串的值是否相同 expected [2] but found [1]。

这里引申一点内容,设置断言后,当执行测试用例的时候,如果实际值于期望值不相等,此时程序会跳出执行,若要程序继续执行,需要将其抛出异常,最好将其封装为一个固有的断言类,每次执行的时候直接调用。

总结

(1)务必掌握 TestNG 的使用方法。

(2)切记 Assert 断言类的使用场景,场景不清晰就根本设置不好断言,另外断言并不是越多越好,代码过多会影响程序的执行效率。

上一篇
下一篇
目录