TestNG官方文档-1

感谢原作者的奉献,原作者博客地址:http://blog.csdn.net/zhu_ai_xin_520/article/details/6199194。
本次使用markdown重新制作一次,带有些地方的修正。

1 - 简介

TestNG 是一个测试框架,它被设计为用来简化广泛的设计需求,从单元测试 (单独测试一个类) 到集成测试 (测试由多个类、报甚至外部框架,例如应用程序服务器,所组成的系统).

编写一个测试通常分为三步:

  • 编写测试业务逻辑,并且在你的代码中插入TestNG annotations .
  • testng.xmlbuild.xml 添加你的测试信息。例如类名,希望运行的组等等.
  • 运行TestNG.

你可以在欢迎
页面上找到一个快速入门的例子。

文档中会使用到如下的概念:

  • 一套测试(suite)由一个XML文件所表示。它能够包含一个或者多个测试, 标记来定义.
  • 标记来表示一个测试,并且可以包含一个或者多个TestNG类.
  • 所谓TestNG类,是一个Java类,它至少包含一个TestNG annotation.它由 标记表示,并且可以包含一个或着多个测试方法。
  • 测试方法,就是一个普通的Java方法,在由@Test标记.

TestNG测试可以通过@BeforeXXX@AfterXXX annotations来标记,允许在特定的生命周期点上执行一些Java逻辑,这些点可以是上述列表中任意的内容。

本手册的其余部分将会解释如下内容:

  • 所有annotation的列表并且给出扼要的解释。它会告诉你很多TestNG所提供的功能,但是你需要详细阅读其余部分来获得关于这些注解更详细的信息.
  • 关于testng.xml文件的说明。它的语法以及你能在里面写什么.
  • 上述内容的详细说明,同时也有结合了annotationtesting.xml文件的使用说明.

2 - Annotations

如下就是在TestNG中可以使用的annotation的速查预览,并且其中给出了属性:

TestNG 类的配置信息
@BeforeSuite @BeforeSuite: 被注解的方法,会在当前suite中所有测试方法之 前 被调用。
@AfterSuite @AfterSuite: 被注解的方法,会在当前suite中所有测试方法之 后 被调用。
@BeforeTest @BeforeTest: 被注解的方法,会在测试(原文就是测试,不是测试方法)运行 前 被调用
@AfterTest @AfterTest: 被注解的方法,会在测试(原文就是测试,不是测试方法)运行后 被调用
@BeforeGroups @BeforeGroups: 被注解的方法会在组列表中之前被调用。这个方法会在每个组中第一个测试方法被调用之前被调用
@AfterGroups @AfterGroups: 被注解的方法会在组列表中之后被调用。这个方法会在每个组中最后一个测试方法被调用之后被调用
@BeforeClass @BeforeClass: 被注解的方法,会在当前类第一个测试方法运行前被调用
@AfterClass @AfterClass: 被注解的方法,会在当前类所有测试方法运行后被调用
@BeforeMethod @BeforeMethod: 被注解的方法,会在运行每个测试方法之前调用
@AfterMethod @AfterMethod: 被注解的方法,会在每个测试方法运行之后被调用
alwaysRun 对于在方法之前的调用(beforeSuite, beforeTest, beforeTestClass 和 beforeTestMethod, 除了beforeGroups): 若为true,这个配置方法无视其所属的组而运行.对于在方法之后的调用(afterSuite, afterClass, ...): 若为true, 这个配置方法会运行,即使其之前一个或者多个被调用的方法失败或者被跳过。
dependsOnGroups 方法所依赖的一组group列表
dependsOnMethods 方法所依赖的一组method列表
enabled 在当前class/method中被此annotation标记的方法是否参与测试(不启用则不在测试中运行)
groups 一组group列表,指明了这个class/method的所属。
inheritGroups 如果是true,则此方法会从属于在类级由@Test注解中所指定的组
@DataProvider 把此方法标记为为测试方法提供数据的方法。被此注释标记的方法必须返回Object[][],其中的每个Object[]可以被分配给测试方法列表中的方法当做参数。那些需要从DataProvider接受数据的@Test方法,需要使用一个dataprovider名字,此名称必须与这个注解中的名字相同。
name DataProvider的名字
@Factory 把一个方法标记为工厂方法,并且必须返回被TestNG测试类所使用的对象们。 此方法必须返回 Object[]。
@Parameters 说明如何给一个@Test方法传参。
value 方法参数变量的列表
@Test 把一个类或者方法标记为测试的一部分。
alwaysRun 如果为true,则这个测试方法即使在其所以来的方法为失败时也总会被运行。
dataProvider 这个测试方法的dataProvider
dataProviderClass 指明去那里找data provider类。如果不指定,那么就当前测试方法所在的类或者它个一个基类中去找。如果指定了,那么data provider方法必须是指定的类中的静态方法。
ependsOnGroups 方法所依赖的一组group列表
dependsOnMethods 方法所以来的一组method列表
description 方法的说明
enabled 在当前class/method中被此annotation标记的方法是否参与测试(不启用则不在测试中运行)
expectedExceptions 此方法会抛出的异常列表。如果没有异常或者一个不在列表中的异常被抛出,则测试被标记为失败。
groups 一组group列表,指明了这个class/method的所属。
invocationCount 方法被调用的次数。
invocationTimeOut 当前测试中所有调用累计时间的最大毫秒数。如果invocationCount属性没有指定,那么此属性会被忽略。
successPercentage 当前方法执行所期望的success的百分比
sequential 如果是true,那么测试类中所有的方法都是按照其定义顺序执行,即使是当前的测试使用parallel="methods"。此属性只能用在类级别,如果用在方法级,就会被忽略。
timeOut 当前测试所能运行的最大毫秒数
threadPoolSize 此方法线程池的大小。 此方法会根据制定的invocationCount值,以多个线程进行调用。注意:如果没有指定invocationCount属性,那么此属性就会被忽略

3 - testng.xml

调用TestNG有多种方式:

  • 使用testng.xml文件
  • 使用ant
  • 通过命令行

本节对testng.xml的格式进行说明(你会在下文找到关于ant和命令行的相关文档)。
目前给testng.xml所使用的DTD可以在主页: http://testng.org/testng-1.0.dtd 上找到(考虑到您能更方便,可以浏览 HTML版)。
下面是个testng.xml文件的例子:


  

  
    
       
    
  
 
  
    
      
      
    
  

你也可以指定包名来替代类名:


 

  
    
      
   
 

在这个例子中,TestNG会查看所有在test.sample的类,并且只保留含有TestNG annotations的类。
你也可以指定要包含和排除掉的组和方法:


  
    
      
      
    
  
  
  
    
      
        
      
    
  

你也可以在testng.xml定义新的group,并且在属性中指明额外的详细信息,例如是否并行运行,使用多少个线程,并且是否正在运行JUnit测试等等……
默认情况下,TestNG按他们找到的XML文件中的顺序运行测试。如果你想在这个文件中列出的类和方法的无序顺序运行,可以设置preserve-order属性设置为false


  
 
    
      
        
        
      
    
 
    
 
  

4 - 运行

TestNG可以使用多种方式调用:

  • 命令行
  • ant
  • Eclipse
  • IntelliJ's IDEA

本节将只介绍如何从命令行运行TestNG。如果您对其他方式感兴趣,那么就点击上面的链接查看更多信息。
假设TestNG已经在你的类路径中,最简单的调用方式如下:
java org.testng.TestNG testng1.xml [testng2.xml testng3.xml ...]
你至少要指定一个XML文件,它描述了你要运行的TestNG suite。此外,还有如下命令行参数:命令行参数

选项 参数 说明
-d 目录 报告会生成的目录 (默认是test-output).
-excludegroups 逗号分隔的组列表 要在当前运行中被排除的组列表.
-groups 逗号分隔的组列表 想要运行的组(e.g. "windows,linux,regression").
-listener 逗号分隔的Java类列表,它们都可以在你的类路径中找到 让你指定你自己的监听器。这些类需要实现org.testng.ITestListener
-parallel 方法/测试 如果指定了,那么在运行测试的时候,所使用的默认的机制就会决定如何去使用并行 线程。反之则不会.这是可以在suite定义中被覆盖的
-reporter 自定义报告监听器的扩展配置 类似于-listener选项,允许在报告器实例中配置JavaBean的样式属性.-reporter com.test.MyReporter:methodFilter=*insert*,enableFiltering=true这个选项不限次数,根据需要一样一个。
-sourcedir 分号间隔的目录列表 使用了JavaDoc类型的annotation的源码所在的目录。这个选项只有你在使用JavaDoc类型的注解时才会有用。(e.g. "src/test" or"src/test/org/testng/eclipse-plugin;src/test/org/testng/testng").
-suitename test suite默认的名字 指明了在命令行中定义的test suite的名字。这个选项在suite.xml或源码指定了不同的名字时会被忽略。如果使用双引号括起来,就可在名字中使用空格。例如:"like this".
-testclass 逗号分隔的类列表,它们必须能在类路径中被找到 逗号分隔的测试类的列表 (e.g. "org.foo.Test1,org.foo.test2").
-testjar 一个jar文件 指定了一个包含了测试类的Jar文件。如果testng.xml在jar文件的根目录被找到,就使用之,反之,jar文件中所有的类都会被当成测试类。
-testname 测试所使用的默认名字 它为在命令行中定义的测试指定了名字。这个选项在suite.xml或源码指定了不同的名字时会被忽略。如果使用双引号括起来,就可在名字中使用空格。例如:"like this"。
-testrunfactory 可以在类路径中找到的Java类 让你指定你自己的测试运行器,相关的类必须实现org.testng.ITestRunnerFactory.
-threadcount 在并行测试的时候默认使用的线程数 并行运行中所使用的最大线程数。只在使用并行模式中有效(例如,使用-parallel选项)。它可以在suite定义中被覆盖。

上面的参数说明可以通过不带任何参数运行TestNG来获得。
你也可以把命令行开关放到文件中,例如说c:/command.txt,之后告诉 TestNG 使用这个文件来解析其参数:

C:> more c:\command.txt
-d test-output testng.xml
C:> java org.testng.TestNG @c:\command.txt

此外TestNG也可以在命令行下向其传递JVM参数。例如:

java -Dtestng.test.classpath="c:/build;c:/java/classes;" org.testng.TestNG testng.xml

如下是TestNG所能理解的属性:

属性 类型 说明
testng.test.classpath 分号分的一系列目录,其中包含了你的测试类 如果指定了这个属性,TestNG就会查找你的测试类而不是类路径。这在你的类路径中有很多类,而大多数又不是测试类,或者在xml文件中使用 package 标记的时候会很方便。

例子:
java org.testng.TestNG -groups windows,linux -testclass org.test.MyTest
注意ant task和testng.xml允许你使用更多的参数来运行TestNG(要包含的方法、指定的参数等等),所以你在学习TestNG的时候考虑使用命令行,因为这样能让你快速进步。

5 - 测试方法、测试类和测试组

5.1 - 测试方法

测试方法被注解为@Test。注释的方法与@Test碰巧返回值将被忽略,除非你设置允许回值设置为true在你的testng.xml


or

5.2 - 测试组

TestNG 允许你将测试方法归类为不同的组。不仅仅是可以声明某个方法属于某个组,而且还可以让组包含其他的组。这样TestNG可以调用或者请求包含一组特定的组(或者正则表达式)而排除其他不需要组的集合。这样,如果你打算将测试分成两份的时候,就无需重新编译。这个特点,会给你在划分组的时候带来很大的灵活性。

组在的testng.xml文件中指定,可以发现无论是标签。指定组标签适用于所有的下方标签。需要注意的是群体标签:如果指定组的“a”在标签中和b在标签中,那么这两个“a”和“b”将被包括在内。

例如,通常将测试划分为两种类别是再常见不过的了:

  • 检查性测试(Check-in test):这些测试在你提交新代码之前就会运行。它们一般都是很快进行的,并且保证没有哪个基本的功能是不好使的。
  • 功能性测试(Functional test):这些测试涵盖你的软件中所有的功能,并且至少每天运行一次,不过你也可能希望他们持续的运行。

典型的来说,检测性测试通常是功能性测试的一个子集。TestNG允许你根据个人感觉来进行组划分。例如,你可能希望把你所有的测试类都划归为"functest"组,并且额外的有几个方法输入"checkintest"组。

public class Test1 {
  @Test(groups = { "functest", "checkintest" })
  public void testMethod1() {
  }
 
  @Test(groups = {"functest", "checkintest"} )
  public void testMethod2() {
  }
 
  @Test(groups = { "functest" })
  public void testMethod3() {
  }
}

通过下面的内容调用TestNG


  
    
      
    
  
  
    
  

以上会运行上面那个类中所有的测试,当药使用checkintest进行调用的时候,就仅仅运行testMethod1()和testMethod2()。
下面是另外一个例子。这次使用正则表达式。假定有些测试方法不应该运行在Linux环境下,你的测试会看起来像:

@Test
public class Test1 {
  @Test(groups = { "windows.checkintest" })
  public void testWindowsOnly() {
  }
 
  @Test(groups = {"linux.checkintest"} )
  public void testLinuxOnly() {
  }
 
  @Test(groups = { "windows.functest" )
  public void testWindowsToo() {
  }
}

然后你就可以使用下面这个 testng.xml 来只运行在Windows下的方法:


  
    
      
    
  
 
  
    
  

注意:TestNG使用的是正则表达式,而不是通配符。注意这二者的区别(例如,"anything" 是匹配于 "."代表点和星号,而不是星号 "").

Method groups

也可以单独排除和包含若干方法:


  
    
      
        
        
      
     
  

这样就可以不用编译而处理任何不需要的方法了,但是我不推荐过分的使用这个技巧,因为如果你要重构你的代码,那么这有可能让你的测试框架出问题(在标签中使用的方法可能再也不会匹配你的方法名了)。

5.3 - 组中组

测试组也可以包含其他组。这样的组叫做“元组"(MetaGroups)"。例如,你可能要定义一个组"all"来包含其他的组,"chekcintest""functest""functest"本身只包含了组windows和linux,而"checkintest"仅仅包含windows。你就可以在属性文件中这样定义:


  
    
      
      
    
  
    
      
      
    
  
    
      
    
  
  
  
    
  

5.4 - 排除组

TestNG 允许你包含组,当然也可以排除之。

譬如说,因为最近的改动,导致当前的测试中断并且,你还没有时间修复这些问题都是司空见惯的。但是,你还需要自己的功能测试可以正确运行,所以,制药简单的让这些不需要的测试失效就可以了。但是别忘记在以后需要的时候,要重新让其生效。

一个简单的办法来解决这个问题就是创建一个叫做"broken"组, 然后使得这些测试方法从属于那个组。例如上面的例子,假设我知道testMethod2()会中断,所以我希望使其失效:

@Test(groups = {"checkintest", "broken"} )
public void testMethod2() {
}

而我所需要做的一切就是从运行中排除这个组:


  
    
      
      
    
  
  
  
    
  

通过这种办法,我们既可以得到整洁的测试运行,同时也能够跟踪那些需要稍后修正的中断的测试。
注意:你可以可以通过使用"enabled"属性来完成,这个属性适用于@Test@Before/After annotation

5.5 - 局部组

可以在类级别定义组,之后还可以在方法级定义组:

@Test(groups = { "checkin-test" })
public class All {
 
  @Test(groups = { "func-test" )
  public void method1() { ... }
 
  public void method2() { ... }
}

在这个类中,method2()类级组"checkin-test"的一部分,而method1()即属于"checkin-test"也属于"func-test"组。

5.6 - 参数

测试方法是可以带有参数的。每个测试方法都可以带有任意数量的参数,并且可以通过使用TestNG的@Parameters向方法传递正确的参数。

设置方式有两种方法:使用testng.xml或者程序编码。

5.6.1 - 使用 testng.xml 设置参数

如果只使用相对简单的参数,你可以在你的testng.xml文件中指定:

@Parameters({ "first-name" })
@Test
public void testSingleString(String firstName) {
  System.out.println("Invoked testString " + firstName);
  assert "Cedric".equals(firstName);
}

在这段代码中,我们让 firstName 参数能够接到XML文件中叫做 first-name参数的值。这个XML参数被定义在 testng.xml


  
  
  <-- ... -->

类似的,它也可以用在@Before/After@Factory注解上:

@Parameters({ "datasource", "jdbcDriver" })
@BeforeMethod
public void beforeTest(String ds, String driver) {
  m_dataSource = ...;                              // 查询数据源的值
  m_jdbcDriver = driver;
}

这次有两个Java参数dsdriver会分别接收到来自属性datasource``和jdbc-driver`所指定的值。

参数也可以通过 Optional 注释来声明:

@Parameters("db")
@Test
public void testNonExistentParameter(@Optional("mysql") String db) { ... }

如果在你的testng.xml文件中没有找到"db",你的测试方法就会使用 @Optional中的值:"mysql"

@Parameters可以被放置到如下位置:

  • 在任何已经被@Test, @Before/After@Factory注解过的地方。
  • 在测试类中至多被放到一个构造函数签。这样,TestNG才能在需要的时候使用 testng.xml 中特定的参数来实例化这个类。这个特性可以被用作初始化某些类中的值,以便稍后会被类中其他的方法所使用。

注意:

  • XML中的参数会按照Java参数在注解中出现的顺序被映射过去,并且如果数量不匹配,TestNG会报错。
  • 参数是有作用范围的。在testng.xml中,你即可以在 标签下声明,也可以在 下声明。如果两个参数都有相同的名字,那么,定义在 中的有优先权。这在你需要覆盖某些测试中特定参数的值时,会非常方便。

5.6.2 - 使用DataProviders提供参数

在 testng.xml 中指定参数可能会有如下的不足:

如果你压根不用testng.xml.
你需要传递复杂的参数,或者从Java中创建参数(复杂对象,对象从属性文件或者数据库中读取的etc...)
这样的话,你就可以使用Data Provider来给需要的测试提供参数。所谓数据提供者,就是一个能返回对象数组的数组的方法,并且这个方法被@DataProvider注解标注:

//这个方法会服务于任何把它(测试方法)的数据提供者的名字为"test1"方法
@DataProvider(name = "test1")
public Object[][] createData1() {
 return new Object[][] {
   { "Cedric", new Integer(36) },
   { "Anne", new Integer(37)},
 };
}
 
//这个测试方法,声明其数据提供者的名字为“test1”
@Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
 System.out.println(n1 + " " + n2);
}

结果会打印

Cedric 36 
Anne 37

@Test标注的方法通过dataProvider属性指明其数据提供商。这个名字必须与@DataProvider(name="...")中的名字相一致。

默认的情况下,数据提供者会查找当前的测试类或者测试类的基类。如果你希望它能够被其他的类所使用,那么就要将其指定为static,并且通过 dataProviderClass属性指定要使用的类:

public class StaticProvider {
  @DataProvider(name = "create")
  public static Object[][] createData() {
    return new Object[][] {
      new Object[] { new Integer(42) }
    }
  }
}
 
public class MyTest {
  @Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
  public void test(Integer n) {
    // ...
  }
}

Data Provider方法可以返回如下两种类型中的一种:

  • 含有多个对象的数组(Object[][]),其中第一个下标指明了测试方法要调用的次数,第二个下标则完全与测试方法中的参数类型和个数相匹配。上面的例子已经说明。
  • 另外一个是迭代器Iterator。二者的区别是迭代器允许你延迟创建自己的测试数据。TestNG会调用迭代器,之后测试方法会一个接一个的调用由迭代器返回的值。在你需要传递很多参数组给测试组的时候,这样你无须提前创建一堆值。

下面是使用这个功能的例子:

@DataProvider(name = "test1")
public Iterator createData() {
  return new MyIterator(DATA);
}

如果你声明的@DataProvider使用java.lang.reflect.Method作为第一个参数,TestNG 会把当前的测试方法当成参数传给第一个参数。这一点在你的多个测试方法使用相同的@DataProvider的时候,并且你想要依据具体的测试方法返回不同的值时,特别有用。

例如,下面的代码它内部的@DataProvider中的测试方法的名字:

@DataProvider(name = "dp")
public Object[][] createData(Method m) {
  System.out.println(m.getName());  // print test method name
  return new Object[][] { new Object[] { "Cedric" }};
}
 
@Test(dataProvider = "dp")
public void test1(String s) {
}
 
@Test(dataProvider = "dp")
public void test2(String s) {
}

所以会显示:

test1 
test2

Data provider可以通过属性parallel实现并行运行:

@DataProvider(parallel = true)
// ...

使用XML文件运行的data provider享有相同的线程池,默认的大小是10.你可以通过修改该在标签中的值来更改:


...

如果你需要让指定的几个data provider运行在不同的线程中,那么就必须通过不同的xml文件来运行。

5.6.3 - 在报告中的参数

在测试方法调用中所使用的参数,会在由TestNG中生成HTML报告里显示出来。下面是几个例子:


5.7 - 依赖方法

有些时候,需要按照特定顺序调用测试方法。对于下面的情况,这非常有用:

  • 在运行更多测试方法之前确保一定数量的测试方法已经完成并成功
  • 要初始化的测试,同时希望这个初始化方法是测试方法,以及(标有@Before/After的方法不会最终报告的一部分)。

TestNG的允许您指定的依赖要么注解或XML格式。

5.7.1 - 依赖和注释

确保在进行更多的方法测试之前,有一定数量的测试方法已经成功完成。
在初始化测试的时候,同时希望这个初始化方法也是一个测试方法(@Before/After不会出现在最后生成的报告中)。
为此,你可以使用@Test中的dependsOnMethodsdependsOnGroups属性。

这两种依赖:

  • Hard dependencies(硬依赖)。所有的被依赖方法必须成功运行。只要有一个出问题,测试就不会被调用,并且在报告中被标记为SKIP。
  • Soft dependencies(软依赖)。 即便是有些依赖方法失败了,也一样运行。如果你只是需要保证你的测试方法按照顺序执行,而不关心他们的依赖方法是否成功。那么这种机制就非常有用。可以通过添加"alwaysRun=true"@Test来实现软依赖。
    硬依赖的例子:
@Test
public void serverStartedOk() {}
 
@Test(dependsOnMethods = { "serverStartedOk" })
public void method1() {}

此例中,method1()依赖于方法serverStartedOk(),从而保证 serverStartedOk()总是先运行。

也可以让若干方法依赖于组:

@Test(groups = { "init" })
public void serverStartedOk() {}
 
@Test(groups = { "init" })
public void initEnvironment() {}
 
@Test(dependsOnGroups = { "init.* })
public void method1() {}

本例中,method1()``依赖于匹配正则表达式"init.*"的组,由此保证了serverStartedOk()initEnvironment()总是先于method1()`被调用。
注意:正如前面所说的那样,在相同组中的调用可是在夸测试中不保证顺序的。

如果你使用硬依赖,并且被依赖方法失败(alwaysRun=false,即默认是硬依赖),依赖方法则不是被标记为FAIL而是SKIP。被跳过的方法会被在最后的报告中标记出来(HTML既不用红色也不是绿色所表示),主要是被跳过的方法不是必然失败,所以被标出来做以区别。

无论dependsOnGroups还是dependsOnMethods都可以接受正则表达式作为参数。对于dependsOnMethods,如果被依赖的方法有多个重载,那么所有的重载方法都会被调用。如果你只希望使用这些重载中的一个,那么就应该使用 dependsOnGroups
更多关于依赖方法的例子,请参考这篇文章,其中也包含了对多重依赖使用继承方式来提供一种优雅的解决方案。

默认情况下,相关的方法是按类分组。例如,如果方法a()依赖于方法的b()和你有一个包含这些方法的类的几个实例(数据工厂提供的数据),这些方法的类的几个实例,然后调用顺序将如下:

a(1)
a(2)
b(2)
b(2)

TestNG的不会运行b(),直到所有实例都调用它们的a()方法。
这种行为可能不希望在某些情况下,例如在测试的标志并签署了Web浏览器的各个国家。在这种情况下,你希望下面的顺序:

signIn("us")
signOut("us")
signIn("uk")
signOut("uk")

对于这个顺序,你可以使用XML属性组group-by-instances。这个属性可以是在有效:

  
or
  

5.7.2 - 在XML中依赖的关系

另外,您也可以在的testng.xml文件中指定的组依赖关系。您可以使用标签来实现这一点:


  
    
      
      
    
  

5.8 - 工厂

工厂允许你动态的创建测试。例如,假设你需要创建一个测试方法,并用它来多次访问一个web页面,而且每次都带有不同的参数:

public class TestWebServer {
  @Test(parameters = { "number-of-times" })
  public void accessPage(int numberOfTimes) {
    while (numberOfTimes-- > 0) {
     // access the web page
    }
  }
}

  
  

 

  
  

 

  
  

参数一旦多起来,就难以管理了,所以应该使用工厂来做:

public class WebTestFactory {
  @Factory
  public Object[] createInstances() {
   Object[] result = new Object[10]; 
   for (int i = 0; i < 10; i++) {
      result[i] = new WebTest(i * 10);
    }
    return result;
  }
}

新的测试类如下:

public class WebTest {
  private int m_numberOfTimes;
  public WebTest(int numberOfTimes) {
    m_numberOfTimes = numberOfTimes;
  }
 
  @Test
  public void testServer() {
   for (int i = 0; i < m_numberOfTimes; i++) {
     // access the web page
    }
  }
}

你的testng.xml只需要引用包含工厂方法的类,而测试实例自己会在运行时创建:


工厂方法可以接受诸如@Test@Before/After所标记的参数,并且会返回 Object[]。这些返回的对象可以是任何类(不一定是跟工厂方法相同的类),并且他们甚至都不需要TestNG注解(在例子中会被TestNG忽略掉)

工厂也可以被应用于数据提供者,并可以通过将@Factory注释无论是在普通的方法或构造函数利用此功能。这里是一个构造工厂的例子:

@Factory(dataProvider = "dp")
public FactoryDataProviderSampleTest(int n) {
  super(n);
}
 
@DataProvider
static public Object[][] dp() {
  return new Object[][] {
    new Object[] { 41 },
    new Object[] { 42 },
  };
}

该示例将TestNG的创建两个测试类,这个构造函数将调用值为41和42的对像。

5.9 - 类级注解

通常 @Test 也可以用来标注类,而不仅仅是方法:

@Test
public class Test1 {
  public void test1() {
  }
 
  public void test2() {
  }
}

处于类级的@Test会使得类中所有的public方法成为测试方法,而不管他们是否已经被标注。当然,你仍然可以用@Test注解重复标注测试方法,特别是要为其添加一些特别的属性时。
例如:

@Test
public class Test1 {
  public void test1() {
  }
 
  @Test(groups = "g1")
  public void test2() {
  }
}

上例中test1()test2()都被处理,不过在此之上test2()现在还属于组 "g1"。

5.10 - 并行运行和超时

您可以以各种方式指示TestNG单独线程运行测试。

5.10.1 - 并行套件

如果你正在运行几个组件文件(e.g. "java org.testng.TestNG testng1.xml testng2.xml")和想让这些组件以一个独立的线程运行这个是非常有用的。你可以使用以下命令行参数来指定线程池的大小。

java org.testng.TestNG -suitethreadpoolsize 3 testng1.xml testng2.xml testng3.xml

相应的ant任务名称为suitethreadpoolsize

5.10.2 - 并行测试,类和方法

你可以通过在suite标签中使用 parallel 属性来让测试方法运行在不同的线程中。这个属性可以带有如下这样的值:





  • parallel="methods": TestNG 会在不同的线程中运行测试方法,除非那些互相依赖的方法。那些相互依赖的方法会运行在同一个线程中,并且遵照其执行顺序。

  • parallel="tests": TestNG 会在相同的线程中运行相同的标记下的所有方法,但是每个标签中的所有方法会运行在不同的线程中。这样就允许你把所有非线程安全的类分组到同一个标签下,并且使其可以利用TestNG多线程的特性的同时,让这些类运行在相同的线程中。

  • parallel="classes": TestNG 会在相同线程中相同类中的运行所有的方法,但是每个类都会用不同的线程运行。

  • parallel="instances": TestNG会在相同线程中相同实例中运行所有的方法,但是两个不同的实例将运行在不同的线程中。

此外,属性thread-count允许你为当前的执行指定可以运行的线程数量。

注意:@Test 中的属性timeOut可以工作在并行和非并行两种模式下。

你也可以指定@Test方法在不同的线程中被调用。你可以使用属性 threadPoolSize来实现:

@Test(threadPoolSize = 3, invocationCount = 10,  timeOut = 10000)
public void testServer() {

上例中,方法testServer会在3个线程中调用10次。此外,10秒钟的超时设定也保证了这三个线程中的任何一个都永远不会阻塞当前被调用的线程。

5.11 - 再次运行失败的测试

每次测试suite出现失败的测试,TestNG 就会在输出目录中创建一个叫做 testng-failed.xml的文件。这个XML文件包含了重新运行那些失败测试的必要信息,使得你可以无需运行整个测试就可以快速重新运行失败的测试。所以,一个典型的会话看起来像:

要注意的是,testng-failed.xml已经包含了所有失败方法运行时需要的依赖,所以完全可以保证上次失败的方法不会出现任何 SKIP。

5.12 - JUnit测试

TestNG 能够运行 JUnit 测试。所有要做的工作就是在testng.classNames属性中设定要运行的JUnit测试类,并且把testng.junit属性设置为true


  
    

TestNG 在这种情况下所表现的行为与 JUnit 相似:

  • junit3

    • 所有类中要运行的测试方法由 test* 开头
    • 如果类中有 setUp() 方法,则其会在每个测试方法执行前被调用
    • 如果类中有 tearDown() 方法,则其会在每个测试方法之后被调用
    • 如果测试类包含 suite() 方法,则所有的被这个方法返回的测试类都会被调用
  • junit4

    • TestNG将使用org.junit.runner.JUnitCore运行器运行你的测试。

5.13 - 程序化运行TestNG

你可以在程序中非常轻松的调用TestNG的测试:

TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { Run2.class });
testng.addListener(tla);
testng.run();

本例中创建了一个TestNG对象,并且运行测试类Run2。它添加了一个 TestListener(这是个监听器) 。你既可以使用适配器类 org.testng.TestListenerAdapter来做,也可以实现org.testng.ITestListener接口。这个接口包含了各种各样的回调方法,能够让你跟踪测试什么时候开始、成功、失败等等。

类似的你可以用testng.xml文件调用或者创建一个虚拟的testng.xml文件来调用。为此,你可以使用这个包org.testng.xml中的类:XmlClass、XmlTest等等。每个类都对应了其在xml中对等的标签。

例如,假设你要创建下面这样的虚拟文件:


  
    
      
    
    

你需要使用如下代码:

XmlSuite suite = new XmlSuite();
suite.setName("TmpSuite");
 
XmlTest test = new XmlTest(suite);
test.setName("TmpTest");
List classes = new ArrayList();
classes.add(new XmlClass("test.failures.Child"));
test.setXmlClasses(classes) ;

之后你可以传递这个XmlSuite给 TestNG:

List suites = new ArrayList();
suites.add(suite);
TestNG tng = new TestNG();
tng.setXmlSuites(suites);
tng.run();

请参阅JavaDocs来获取完整的API。

5.14 - BeanShell于高级组选择

如果不够用,那就是用BeanShell表达式来决定是否一个特定的测试方法应该被包含进来。只要在标签下使用这个表达式就好了:


   
     
       
     
   
  

当在testng.xml文件中找到

你可能感兴趣的:(TestNG官方文档-1)