1. OverView
TestNG是一种基于注释的测试框架,通过添加诸如灵活的装置、测试分类、参数测试和依赖方法等特性来克服JUnit的一些不足之处。此外,TestNG运行于Java 5.0(通过注释)和Java 1.4(通过JavaDoc样式的注释)之上。本篇博文仅将和JUnit相同功能做简单介绍,另外testNG独有功能将在以后撰文介绍。
testNG的eclipse插件地址:http://beust.com/eclipse
2. 概念介绍
2.1 简单测试
在附件中的代码包中有生产代码 Money 类。请看以下对 Money 类的测试代码(所有测试代码也可以在附件的代码包中查找)
package main; import org.testng.annotations.Test; public class TestSample { @Test public void add() { Money m12CHF = new Money(12, "CHF"); Money m14CHF = new Money(14, "CHF"); Money expected = new Money(26, "CHF"); Money result = m12CHF.add(m14CHF); assert true : expected.equals(result); } }
在这段测试代码中有几点需要注意和 Junit 测试代码不同之处:
1 该测试方法主要测试 Money 类中 add ()方法是否能正确对货币进行操作。和 Junit 中对测试方法用 @Test 相同。方法名字可以自行定义 。
2 测试类也不需要继承 TestCase 。testNG 中测试类不需要继承任何 接口和类。
3 可以使用 Junit 中 断言形式 。但也可以使用代码中所写断言形式。
特性测试
请先阅读一遍下列代码,然后我会对这段代码的一些 特性进行详细说明。
package main; import java.util.ArrayList; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class TestFixture { private Money f12CHF; private Money f14CHF; private Money f26CHF; private Money f28USD; @BeforeClass public void setUp() { f12CHF = new Money(12, "CHF"); f14CHF = new Money(14, "CHF"); f26CHF = new Money(26, "CHF"); f28USD = new Money(28, "USD"); } @Test public void testAdd() { Money result = f12CHF.add(f14CHF); assert true : f26CHF.equals(result); } // @Test(enabled = false, expectedExceptions = // IndexOutOfBoundsException.class) @Test(enabled = true, expectedExceptions = IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); } @Test(timeOut = 1000) public void testTimeOut() throws InterruptedException { Thread.sleep(1000); // Thread.sleep(1001); Money result = f12CHF.add(f14CHF); } @AfterClass public void tearDown() { f12CHF = null; f14CHF = null; f26CHF = null; f28USD = null; } }
1 . @Before Class和 @After Class
这两个属性表明标注的方法在当前被执行测试类的第一个测试方法之前和之后执行。 这两个方法名可以自行定义为其他任何名字。
2 . @Test(enabled = true/false, expectedExceptions = XXXException.class )
TDD中,对错误的测试,我们以前只能通过 fail 来产生一个错误,并在 try 块里面 断言 来测试。现在,通过 @Test 中的 expectedExceptions 属性就可以实现了。 expectedExceptions 属性的值是一个异常的类型,如代码中的 IndexOutOfBoundsException.class 。 enable属性表明是否启用该标注方法。(可以通过切换注释上一行注解,运行查看 结果)
3 .@Test(timeOut= … )
该 标记 传入了一个时间(毫秒)给测试方法,如果测试方法在指定的时间之内没有运行完,则测试会失败,即使被测试方法测试正确也会失败。该标记主要用于测试被测试方法运行所需时间,即用于方法的简单性能测试。( 也可以通过切换注释Thread.sleep(1001),运行查看 结果 )
参数测试
有时候要对某一特定方法传入各种不同的参数值,用来测试这个方法的健壮性。以前TDD 中必须为每种参数值单独写一个独立的测试方法。这样就造成很多测试代码测试的都是同一方法,只是传入的参数值有不同。testNG同 Junit4 中一样只需要一个测试方法就能针对 N 种不同参数值进行 N 次测试。试看如下代码:
package main; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Administrator */ public class TestParameter { private static Money f12CHF; @BeforeClass public static void setUp() { f12CHF = new Money(12, "CHF"); } /** * 第一个注意点 * 参数化测试必须的构造函数 * @return */ @DataProvider(name = "test-provider") public static Object[][] words() { return new Object[][] { { new Money(23, "CHF"), new Money(11, "CHF") }, { new Money(28, "CHF"), new Money(16, "CHF") } }; } /** * 第二个注意点 *@param expected 期望的测试结果,对应参数集中的第一个参数 *@param target 测试数据,对应参数集中的第二个参数 *Test属性dataProvider值和构造函数的dataProvider属性name值相对应 *实际需要测试的方法 */ @Test(dataProvider = "test-provider") public void add(Money expected, Money target) { assert true : expected.equals(f12CHF.add(target)); } }
请详细查看注释中所标注的注意点。首先 设置 测试类构造方法。用此方法进行参数初始化。该方法 返回一个 Object[][] 类型。需要用 @DataProvider 注解来修饰该方法,并设置name值。在该方法内部,仅仅创建一个多维 Object 数组 。之后在需要测试的方法中设置@Test的dataProvider属性。其值要和上面 @DataProvider修饰的 方法中的name值相同。然后运行 testNG 后,测试通过后的界面如下图:
由图可知执行该测试类时,通过 add ()
测试方法运行两次,将代码中 words 方法里的每个值对运行一次。
套件测试
相比 Junit 的套件测试, testNG套件测试可以通过testng.xml文件来实现。代码示例如下:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="test suite" verbose="1" parallel="false" thread-count="2"> <test name="main"> <classes> <class name="main.TestSample" /> <class name="main.TestFixture" /> <class name="main.TestParameter" /> </classes> </test> </suite>
这里略微详细讲一下testng.xml文件中相关标签和属性。
<suite>这是testng.xml文件的根标签,描述一个测试套件。套件由多个<test>组成。属性介绍如下:
name:套件名称,是必需要有的。
verbose:执行的输出详细程度。因为testng会输出html格式的测试报告。因此该属性决定报告详细程度。程度值由0-10.0是没有,10是最详细。不是必需有的。
parallel:表明是否利用不同线程来执行测试套件。值有tests,methods或none。不是必需有的。
thread-count:如果启用上面parallel模式,使用线程数。而且如果启用,默认值是5。不是必需有的。
上面parallel和thread-count属性通常都是一块用的。
<suite>标签可以包括1到多个<test>标签。这里name属性是<test>的必须属性,代表测试名称。
<classes>和<class>标签都是<test>子标签,定义在测试中所包含的测试类。name属性也是必须属性,而且必须是该测试类的全路径名称。如代码中的main.TestSample.
可以在eclipse中点击testng.xml文件,右键run as中的testNG,结果如下图:
如图,可看到包中所有的测试类都测试运行通过。
可以通过在eclipse中的window-->Preferences中设置testng的测试报告输出路径。如下图:
这里可见我本机设置的是绝对输出路径,可去该路径下双击index.html文件查看测试报告,如下图: