zoukankan      html  css  js  c++  java
  • TestNG(一)

    一、TestNG是什么?

    TestNG是一个开源的单元测试框架,灵感来源于JUnit和NUnit。

    1. 注解
    2. 参数化测试
    3. 支持依赖测试方法
    4. 支持组概念
    5. 支持多线程测试
    6. 灵活的配置

    二、TestNG怎么运行?

    1. 通过TestNG配置文件
    2. 直接运行有@Test标签的java文件
    3. 命令行

    三、TestNG的注解

    ⼀个suite(套件) 由⼀个或多个测试组成。
    ⼀个test(测试) 由⼀个或多个类组成。
    ⼀个class(类) 由⼀个或多个⽅法组成。

    @BeforeSuite/@AfterSuite:被注释⽅法将在某个测试套件运⾏前/某个测试套件所有测试⽅法运⾏后执⾏
    @BeforeTest/@AfterTest:被注释⽅法将在测试运⾏前/某个测试所有测试⽅法运⾏后执⾏
    @BeforeClass/@AfterClass:被注释⽅法将在当前类的第⼀个测试⽅法调⽤前/当前类所有测试⽅法运⾏后运⾏
    @BeforeMethod/@AfterMethod:被注释⽅法将在每⼀个测试⽅法调⽤前/后运⾏
    @BeforeSuite/@AfterSuite/@BeforeTest/@AfterTest可以对不同的测试类⽣效,其他注解只在本类范围内⽣效

    执行顺序:
    @BeforeSuite->@BeforeTest->@BeforeClass->
    {@BeforeMethod->@Test->@AfterMethod}
    ->@AfterClass->@AfterTest->@AfterSuite
    其中{}内的与多少个@Test,就循环执⾏多少次

    举个栗子:

    //Java文件:
    public class TestAnnotation1 {
      @BeforeSuite
      public void beforeSuite() {
         System.out.println("===Suite执⾏之前操作====");
      }
      @AfterSuite
      public void afterSuite() {
         System.out.println("===Suite执⾏之后操作==");
      }
      @BeforeTest
      public void beforeTest() {
        System.out.println("***TestAnnotation1--Test执⾏之前操作");
      }
      @AfterTest
      public void afterTest() {
        System.out.println("===TestAnnotation1--Test执⾏之后操作");
      }
      @BeforeClass
      public void beforeClass() {
        System.out.println("****TestAnnotation1--Class执⾏之前操作*");
      }
      @AfterClass
      public void afterClass() {
        System.out.println("===TestAnnotation1--Class执⾏之后操作==");
      }
      @BeforeMethod
      public void beforeMethod() {
        System.out.println("***TestAnnotation1--Method执⾏之前操作");
      }
      @AfterMethod
      public void afterMethod() {
        System.out.println("===TestAnnotation1--Method执⾏之后操作=");
      }
    
      @Test
      public void test(){}
      }
    
    //testng.xml文件
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="TestSuite">
      <test name="Test1">
        <classes>
          <class name="com.test.testng.TestAnnotation1"/>
        </classes>
    </test>
    </suite> 

    四、TestNG的参数化

    
    
    public class SimpleTest {
      @BeforeClass
      public void BeforeClass() {
        System.out.println("Before Class");
      }
      @BeforeMethod
      public void BeforeMethod() {
        System.out.println("Before Method");
      }
      @Test
      public void testAdd() {
        Integer sum1 = MathSolution.Add(1, 2);
        assertThat("Add 1 + 2 结果错误", sum1, equalTo(3));
      }
      @Test
      public void testAdd2() {
        Integer sum2 = MathSolution.Add(null, null);
        assertThat("Add null + null 结果错误", sum2, equalTo(null));
      }
      @Test
      public void testAdd3() {
        Integer sum3 = MathSolution.Add(Integer.MAX_VALUE, 
        Integer.MAX_VALUE);
        assertThat("Too Big", sum3, equalTo(null));
      }
    } 

    这段代码有啥缺点?
    被测试数据散落在程序中,维护性差、可读性差、case构造起来繁琐
    那我们怎么办呢?当然是参数化了。

    TestNG参数化有几种方式:
    1.使用@DataProvider
    2.xml配置文件

    @DataProvider:标记⼀个⽅法⽤于为测试⽅法提供数据。
    被注释的⽅法必须返回Object[][](Iterator<Object[]>), 其中每个Object[]可以指派为这个测试⽅法的参数列表。
    从DataProvider接收数据,@Test⽅法需要指定dataProvider属性。
    //DataProvider栗子
    public class DataProviderTest {
      @BeforeClass
      public void BeforeClass() {
        System.out.println("Before Class");
      }
      @BeforeMethod
      public void BeforeMethod() {
        System.out.println("Before Method");
      }
      @DataProvider
      public Object[][] paramData() {
        return new Object[][] {
          {"Add 1 + 2", 1, 2, 3},
          {"Add null + null", null, null, null},
          {"Add Big", Integer.MAX_VALUE, Integer.MAX_VALUE, null}
        };
      }
      //指定使用哪个DataProvider
      @Test(dataProvider="paramData")
      public void testDataProvider(String caseDetail, Integer num1, Integer num2, Integer expect) {
        Integer sum = MathSolution.Add(num1, num2);
        assertThat(caseDetail, expect, equalTo(sum));
      }
    } 

    参数化之后代码是不是看起来更加简洁了?我们也可以用文件做为数据源,DB做为数据源。不妨自己动手实验一番吧~
    如果再做一个数据源适配器,是不是就更好了?

     

    xml提供参数,在xml中定义parameter,Java文件中使用@Parameter注解来引用参数。下面来看断代码。

    //Java文件,引用参数sql
    public class ConfDataProviderTest {
      private String sql;
      @Parameters({"sql"})
      @BeforeClass
      public void beforeClass(String sql) {
        this.sql = sql;
      }
      @DataProvider
      public Iterator<Object[]> confData() throws ClassNotFoundException, SQLException {
        DataProvider_byDB dataProvider_byDB = new 
        DataProvider_byDB("127.0.0.1", "5002", "test_testng", "testng", "testng", sql);
        return dataProvider_byDB.getDBData();
      }
      @Test(dataProvider = "confData")
      public void testDBDataProvider(Map<String, String> data) {
        Integer num1 = (data.get("num1") == null) ? null : Integer.valueOf(data.get("num1"));
        Integer num2 = (data.get("num2") == null) ? null : Integer.valueOf(data.get("num2"));
        Integer expect = (data.get("expect") == null) ? null : Integer.valueOf(data.get("expect"));
        String caseDetail = data.get("case_detail").toString();
        Integer sum = MathSolution.Add(num1, num2);
        assertThat(caseDetail, expect, equalTo(sum));
      }
    }
    
    //xml文件,提供参数sql
    <test name="Test3">
      <parameter name="sql" value="select * from dataprovider where project_name='Test_TestNG'"/>
      <classes>
        <class name="com.test.testng.Lesson2DataProvider.DataProviderTest"/>
        <class name="com.test.testng.Lesson2DataProvider.DBDataProviderTest"/>
        <class name="com.test.testng.Lesson2DataProvider.ExcelDataProviderTest"/>
        <class name="com.test.testng.Lesson2DataProvider.ConfDataProviderTest"/>
      </classes>
    </test> 

    介绍完@DataProvider注解,不得不提一下另一个跟他很相似的注解@Factory
    @Factory是用来创建一个测试类的多个实例,每个实例的属性不同,以执行不同的测试。

    @Factory与@DataProvider有啥区别呢?

    • DataProvider:为测试用例提供参数,有多少组参数就会执行多少次用例,因此它是一个让测试类实例的某个方法执行多次,但每次执行都使用同一个实例。
    • Factory:创建一个测试类的多个实例,每个实例中的所有测试用例都会被执行,因此它是一个测试类被执行多次,每次执行采用的是不同实例。

    看个栗子,@Factory:

    public class Test1 {
      private int count;
      public Test1(int count) {
        this.count = count;
      }
      //两个不同实例
      @Test
      public void test() {
        System.out.println("Test1-不同实例地址-" + this);
        for (int i = 0; i < count; i++) {
          System.out.println("Test1-test-" + i);
        }
      }
    } 
    //Factory
    public class FactoryTest {
      @Factory
      public Object[] factoryTest1() {
        return new Object[]{new Test1(1), new Test1(2)};
      }
    }

    执行结果如下,可以看到是两个不同的实例:

     再看一个DataProvider的栗子:

    public class Test2 {
      @DataProvider
      public Object[][] getData() {
        return new Object[][]{
          {1},
          {2}
        };
      }
      //两个相同实例
      @Test(dataProvider = "getData")
      public void test(int count) {
        System.out.println("Test2-相同实例地址-" + this);
        for (int i = 0; i < count; i++) {
          System.out.println("Test2-test-" + i);
        }
      }
    }

    执行结果如下,可以看到是两个相同的地址:

     


    声明 欢迎转载,但请保留文章原始出处:) 博客园:https://www.cnblogs.com/chenxiaomeng/ 如出现转载未声明 将追究法律责任~谢谢合作
  • 相关阅读:
    重构构建的平凡之路
    andriod CheckBox
    andriod 用户名和密码
    andriod ==和equals
    android布局--Android fill_parent、wrap_content和match_parent的区别
    Android 五大布局
    一个帖子学会Android开发四大组件
    Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
    andriod VideoView
    arcgis andriod 长按获得当前信息
  • 原文地址:https://www.cnblogs.com/chenxiaomeng/p/14851906.html
Copyright © 2011-2022 走看看