2023拉

Junit 4 和 TestNG 做个功能特征的对比

上一篇 / 下一篇  2014-06-28 23:10:54 / 个人分类:Selenium测试

  

下图将会对Junit 4 和 TestNG 做个功能特征的对比。

 

注解支持

Junit 4 和 TestNG 在注解方面的实现非常相似。

特性JUnit 4TestNG
测试注解@Test@Test
测试套件在执行之前需要执行的@BeforeSuite
测试套件在执行之后需要执行的@AfterSuite
在测试之前需要执行的@BeforeTest
在测试之后需要执行的@AfterTest
在一个测试方法所属于的任意一个组的第一个方法被调用之前执行@BeforeGroups
在一个测试方法所属于的任意一个组的最后一个方法被调用之后执行@AfterGroups
在当前类的第一个测试方法调用之前执行@BeforeClass@BeforeClass
在当前类的最后一个测试方法调用之后执行@AfterClass@AfterClass
每个测试方法之前需要执行@Before@BeforeMethod
每个测试方法之后需要执行@After@AfterMethod
忽略@ignore@Test(enabled=false)
预期异常@Test(expected = ArithmeticException.class)@Test(expectedExceptions = ArithmeticException.class)
超时@Test(timeout = 1000)@Test(timeout = 1000)

JUnit 4 和 TestNG 之间注解方面的区别主要有以下几点:

  1. 在Junit 4 中,如果我们需要在方法前面使用@BeforeClass@AfterClass,那么该测试方法则必须是静态方法。TestNG 在方法定义部分则更加的灵活,它不需要类似的约束。
  2. 3个附加的setUp/tearDown级别:套件和分组(@Before/AfterSuite, @Before/AfterTest, @Before/AfterGroup)。想了解详细的请看这里

JUnit 4

@BeforeClasspublicstaticvoidoneTimeSetUp(){// one-time initialization codeSystem.out.println("@BeforeClass - oneTimeSetUp");}

TestNG

@BeforeClasspublicvoidoneTimeSetUp(){// one-time initialization codeSystem.out.println("@BeforeClass - oneTimeSetUp");}

在Junit 4中,注解的命名是比较令人困惑的,例如Before,AfterandExpected,我们不是很确切的能理解在方法前面有BeforeAfter这样的注解是做什么的,同样Expected也如此。TestNG在这方面做的就好很多,注解使用了BeforeMethodAfterMethodExpectedException,这样的名字就非常好理解了。

异常测试

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

JUnit 4

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

TestNG

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

忽略测试

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

JUnit 4

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

TestNG

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

时间测试

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

JUnit 4

@Test(timeout=1000)publicvoidinfinity(){while(true);}

TestNG

@Test(timeOut=1000)publicvoidinfinity(){while(true);}

套件测试

套件测试就是把几个单元测试组合成一个模块,然后运行,这个特性两个框架均已实现。然而却是用了两个不同的方式来实现的。

JUnit 4

@RunWith@Suite注解被用于执行套件测试。下面的代码是所展示的是在JunitTest5被执行之后需要JunitTest1JunitTest2也一起执行。所有的声明需要在类内部完成。

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

TestNG

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

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" ><suitename="My test suite"><testname="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")publicvoidtestingMethod1(){System.out.println("Method - testingMethod1()");}@Test(groups="method2")publicvoidtestingMethod2(){System.out.println("Method - testingMethod2()");}@Test(groups="method1")publicvoidtestingMethod1_1(){System.out.println("Method - testingMethod1_1()");}@Test(groups="method4")publicvoidtestingMethod4(){System.out.println("Method - testingMethod4()");}

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

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

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

参数化测试

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

JUnit 4

@RunWith@Parameter注解用于为单元测试提供参数值,@Parameters必须返回 List[],参数将会被作为参数传给类的构造函数。

@RunWith(value=Parameterized.class)publicclassJunitTest6{privateintnumber;publicJunitTest6(intnumber){this.number=number;}@ParameterspublicstaticCollection<Object[]>data(){Object[][]data=newObject[][]{{1},{2},{3},{4}};returnArrays.asList(data);}@TestpublicvoidpushTest(){System.out.println("Parameterized Number is : "+number);}}

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

TestNG

使用XML文件或者@DataProvider注解来给测试提供参数。

XML文件配置参数化测试

只是在方法上声明@Parameters注解,参数的数据将由 TestNG 的 XML 配置文件提供。这样做之后,我们可以使用不同的数据集甚至是不同的结果集来重用一个测试用例。另外,甚至是最终用户,QA 或者 QE 可以提供使用 XML 文件来提供他们自己的数据来做测试。

Unit Test

publicclassTestNGTest6_1_0{@Test@Parameters(value="number")publicvoidparameterIntTest(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.fsecure.demo.testng.TestNGTest6_0"/></classes></test></suite>

@DataProvider注解做参数化测试

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

@DataProvider可以使用 Vector, String 或者 Integer 类型的值作为参数

@Test(dataProvider="Data-Provider-Function")publicvoidparameterIntTest(Classclzz,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")publicObject[][]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")publicvoidparameterIntTest(TestNGTest6_3_0clzz){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")publicObject[][]parameterIntTestProvider(){TestNGTest6_3_0obj=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来实现了依赖测试的功能,如下:

@Testpublicvoidmethod1(){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了。

参考资料

TestNG

————

http://en.wikipedia.org/wiki/TestNG

http://www.ibm.com/developerworks/java/library/j-testng/

http://testng.org/doc/index.html

http://beust.com/weblog/

JUnit

———–

http://en.wikipedia.org/wiki/JUnit

http://www.ibm.com/developerworks/java/library/j-junit4.html

http://junit.sourceforge.net/doc/faq/faq.htm

http://www.devx.com/Java/Article/31983/0/page/3

http://ourcraft.wordpress.com/2008/08/27/writing-a-parameterized-junit-test/

TestNG VS JUnit

——————

http://docs.codehaus.org/display/XPR/Migration+to+JUnit4+or+TestNG

http://www.ibm.com/developerworks/java/library/j-cq08296/index.html

http://www.cavdar.net/2008/07/21/junit-4-in-60-seconds/


TAG:

 

评分:0

我来说两句

Open Toolbar