Junit4与TestNG对比

作者: 测试开发栈 | 来源:发表于2017-03-13 09:40 被阅读240次

Junit4和TestNG作为最常用的两大测试框架,它们有什么差异呢,今天的主题就是对它们做一个全方位的对比(偷偷的告诉你们,自动化测试相关岗位的面试会经常问这个)。

一、注解支持

  1. Junit 4 和 TestNG 在注解方面的实现非常相似,它们之间的注解对比如下表:


    Paste_Image.png
  2. JUnit 4 和 TestNG 之间注解方面的区别主要有以下几点:
    a.在Junit 4 中,如果我们需要在方法前面使用@BeforeClass和@AfterClass,那么该测试方法则必须是静态方法。TestNG 在方法定义部分则更加的灵活,它不需要类似的约束。
    b. 在Junit 4中,注解的命名是比较令人困惑的,例如 Before, After and Expected,我们不是很确切的能理解在方法前面有Before和After这样的注解是做什么的,同样Expected也如此。TestNG在这方面做的就好很多,注解使用了BeforeMethod,AfterMethod和ExpectedException,这样的名字就非常好理解了。

二、异常测试

异常测试的意思是在单元测试中应该抛出什么异常是合理的,这个特性在两个框架都已经实现。
JUnit 4

@Test(expected = ArithmeticException.class) 
public void divisionWithException() { 
    inti = 1/0;
}

TestNG

@Test(expectedExceptions = ArithmeticException.class) 
public void divisionWithException() { 
    inti = 1/0;
}

三、忽略测试

忽略测试意思是在单元测试哪些是可以被忽略的,这个特性在两个框架都已经实现。
JUnit 4

@Ignore("Not Ready to Run") 
@Test
public void divisionWithException() { 
    System.out.println("Method is not ready yet");
}

TestNG

@Test(enabled=false)
public void divisionWithException() { 
    System.out.println("Method is not ready yet");
}

四、超时测试

时间测试意思是如果一个单元测试运行的时间超过了一个指定的毫秒数,那么测试将终止并且标记为失败的测试,这个特性在两个框架都已经实现。
JUnit 4

@Test(timeout = 1000) 
public void infinity() { 
    while(true); 
}

TestNG

@Test(timeOut = 1000) 
public void infinity() { 
    while(true); 
}

五、套件测试

套件测试就是把几个单元测试组合成一个模块,然后运行,这个特性两个框架均已实现。然而却是用了两个不同的方式来实现的。
JUnit 4
@RunWith 和 @Suite注解被用于执行套件测试。下面的代码是所展示的是在JunitTest5被执行之后需要JunitTest1 和 JunitTest2也一起执行。所有的声明需要在类内部完成。

@RunWith(Suite.class)
@Suite.SuiteClasses({
    JunitTest1.class,
    JunitTest2.class
})
public class JunitTest5 {
}

TestNG
执行套件测试是使用XML文件配置的方式来做。下面的 XML 的文件可以使得TestNGTest1和TestNGTest2一起执行。

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd">
<suite name="My test suite">
  <test name="testing">
    <classes>
       <classname="com.fsecure.demo.testng.TestNGTest1"/>
       <classname="com.fsecure.demo.testng.TestNGTest2"/>
    </classes>
  </test>
</suite>

TestNG可以在这块做的更好,使用了组的概念,每个方法都可以被分配到一个组里面,可以根据功能特性来分组。例如:下面是一个有4个方法,3个组(method1, method2 和 method4)的类

@Test(groups="method1")
public void testing Method1() { 
  System.out.println("Method - testingMethod1()");
} 
@Test(groups="method2")
public void testingMethod2() { 
    System.out.println("Method - testingMethod2()");
} 
@Test(groups="method1")
public void testingMethod1_1() { 
    System.out.println("Method - testingMethod1_1()");
} 
@Test(groups="method4")
public void testingMethod4() { 
    System.out.println("Method - testingMethod4()");
}

下面XML文件定义了一个只是执行methed1的组的单元测试:

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd">
<suite name="My test suite">
  <test name="testing">
    <groups>
      <run>
        <include name="method1"/>
      </run>
    </groups>
    <classes>
       <classname="com.alany.demo.testng.TestNGTest5_2_0"/>
    </classes>
  </test>
</suite>

使用分组的概念,集成测试就会更加强大。例如,我们可以只是执行所有测试中的组名为method1的测试。

六、参数化测试

参数化测试意思是给单元测试传多个参数值。这个特性在JUnit 4 和TestNG。然后两个框架实现的方式却完全不同。

  1. JUnit 4
    @RunWith 和 @Parameter 注解用于为单元测试提供参数值,@Parameters必须返回 List,参数将会被作为参数传给类的构造函数。
@RunWith(value = Parameterized.class)
publicclassJunitTest6 {
 
     privateintnumber;
 
     publicJunitTest6(intnumber) {
        this.number = number;
     }
 
     @Parameters
     publicstaticCollection<Object[]> data() {
       Object[][] data = newObject[][] { { 1}, { 2}, { 3}, { 4} };
       returnArrays.asList(data);
     }
 
     @Test
     publicvoidpushTest() {
       System.out.println("Parameterized Number is : "+ number);
     }
}

它在使用上有许多的限制;我们必须遵循 JUnit 的方式去声明参数,参数必须通过构造函数的参数去初始化类的成员来用于测试。返回的参数类型必须是List [],数据已经被限定为String或者是一个原始值。

  1. TestNG
    使用XML文件或者@DataProvider注解来给测试提供参数。
    XML文件配置参数化测试
    只是在方法上声明@Parameters注解,参数的数据将由 TestNG 的 XML 配置文件提供。这样做之后,我们可以使用不同的数据集甚至是不同的结果集来重用一个测试用例。另外,甚至是最终用户,QA 或者 QE 可以提供使用 XML 文件来提供他们自己的数据来做测试。
    Unit Test
public class TestNGTest6_1_0 {
 
   @Test
   @Parameters(value="number")
   public void parameterIntTest(intnumber) {
      System.out.println("Parameterized Number is : "+ number);
   }
 
  }

XML 文件

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suitename="My test suite">
  <testname="testing">
 
    <parametername="number"value="2"/> 
 
    <classes>
       <classname="com.alany.demo.testng.TestNGTest6_0"/>
    </classes>
  </test>
</suite>

@DataProvider 注解做参数化测试
使用XML文件初始化数据可以很方便,但是测试偶尔需要复杂的类型,一个String或原始值并不能完全满足。 TestNG 的@ DataProvider的注解,可以更好的把复杂的参数类型映射到一个测试方法来处理这种情况。
@DataProvider 可以使用 Vector, String 或者 Integer 类型的值作为参数

@Test(dataProvider = "Data-Provider-Function")
public void parameterIntTest(Class clzz, String[] number) {
   System.out.println("Parameterized Number is : "+ number[0]);
   System.out.println("Parameterized Number is : "+ number[1]);
}
//This function will provide the patameter data
@DataProvider(name = "Data-Provider-Function")
public Object[][] parameterIntTestProvider() {
    returnnewObject[][]{
       {Vector.class, newString[] {"java.util.AbstractList", "java.util.AbstractCollection"}},
       {String.class, newString[] {"1", "2"}},
       {Integer.class, newString[] {"1", "2"}}
    };
}

@DataProvider 作为对象的参数
P.S “TestNGTest6_3_0” 是一个简单的对象,使用了get和set方法。

@Test(dataProvider = "Data-Provider-Function")
public void parameterIntTest(TestNGTest6_3_0 clzz) {
   System.out.println("Parameterized Number is : "+ clzz.getMsg());
   System.out.println("Parameterized Number is : "+ clzz.getNumber());
} 
//This function will provide the patameter data
@DataProvider(name = "Data-Provider-Function")
public Object[][] parameterIntTestProvider() {
 
    TestNGTest6_3_0 obj = newTestNGTest6_3_0();
    obj.setMsg("Hello");
    obj.setNumber(123);
 
    returnnewObject[][]{
        {obj}
    };
}

TestNG的参数化测试使用起来非常的友好和灵活 (不管是XML配置还是在类里面注解的方式). 它可以使用许多复杂的数据类型作为参数的值,并且没有什么限制。如上面的例子所示, we even can pass in our own object (TestNGTest6_3_0) for parameterized test

七、依赖测试

参数化测试意味着测试的方法是有依赖的,也就是要执行的的方法在执行之前需要执行的部分。如果依赖的方法出现错误,所有的子测试都会被忽略,不会被标记为失败。
JUnit 4
JUnit 框架主要聚焦于测试的隔离,暂时还不支持这个特性。
TestNG
它使用dependOnMethods来实现了依赖测试的功能,如下:

@Test
publicvoidmethod1() {
   System.out.println("This is method 1");
}
 
@Test(dependsOnMethods={"method1"})
publicvoidmethod2() {
    System.out.println("This is method 2");
}

如果method1()成功执行,那么method2()也将被执行,否则method2()将会被忽略。

八、讨论总结

当我们做完所有特性的对比以后,我建议使用 TestNG 作为 Java 项目的主要单元测试框架,因为 TestNG 在参数化测试、依赖测试以及套件测试(组)方面功能更加强大。TestNG 意味着高级的测试和复杂的集成测试。它更加的灵活,特别是对大的套件测试。另外,TestNG 也涵盖了 JUnit4 的全部功能。那就没有任何理由使用 Junit了。

PS: 更多原创技术好文和资料,请关注下方公众号:“测试开发栈”公众号是由具有多年测试、开发经验的老兵们共同管理和运营,旨在分享原创测试、开发相关技术,包括但不限于:测试方向:Web自动化测试、移动端自动化测试、Web服务端测试、接口测试等;开发方向:Java开发、Android开发、前端开发等;期望我们的经验和技术分享能让你每天都成长和进步,早日成为技术大牛~欢迎大家分享和转发我们的文章(分享转发请保留文章出处),以便让更多的朋友关注我们,同时也欢迎加入我们的QQ群交流和提问:427020613


相关文章

网友评论

    本文标题:Junit4与TestNG对比

    本文链接:https://www.haomeiwen.com/subject/kbuxnttx.html