【译】TestNG官方文档中文版(08)—— 测试方法、测试类和测试组(5.13-5.20)

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中对等的标签。

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

<suite name="TmpSuite" >
 
<test name="TmpTest" >
   
<classes>
     
<class name="test.failures.Child"  />
   
<classes>
   
</test>
</suite>

你需要使用如下代码:

XmlSuite suite = new XmlSuite();
suite
.setName("TmpSuite");

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

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

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

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

 

5.14 - BeanShell于高级组选择

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

<test name="BeanShell test">
   
<method-selectors>
     
<method-selector>
       
<script language="beanshell"><![CDATA[
         groups
.containsKey("test1")
       
]]>
</script>
     
</method-selector>
   
</method-selectors>
 
<!-- ... -->

当在 testng.xml 文件中找到 <script> 标签后,TestNG 就会忽略在当前<test>标签内组和方法的的 <include> 和 <exclude> 标签: BeanShell 就会成为测试方法是否被包含的唯一决定因素。

下面是关于BeanShell 脚本的额外说明:

  • 必须返回一个boolean值。除了这个约束以外,任何有效的 BeanShell 代码都是允许的 (例如,可能需要在工作日返回 true 而在周末返回 false,这样就允许你可以依照不同的日期进行测试)。
  • TestNG 定义了如下的变量供你调用:
    java.lang.reflect.Method method:  当前的测试方法
    org.testng.ITestNGMethod testngMethod:  当前测试方法的描述
    java.util.Map<String, String> groups:  当前测试方法所属组的映射
  • 你也可能需要使用 CDATA 声明来括起Beanshell表达式(就像上例)来避免对XML保留字冗长的引用。

5.15 - 注解转换器

TestNG 允许你在运行时修改所有注解的内容。在源码中注解大多数时候都能正常工作的时时非常有用的(这句原文就是这意思,感觉不太对劲),但是有几个情况你可能会改变其中的值。

为此,你会用到注解转换器( Annotation Transformer )。

所谓注解转换器,就是实现了下面接口的类:

public interface IAnnotationTransformer {

 
/**
   * This method will be invoked by TestNG to give you a chance
   * to modify a TestNG annotation read from your test classes.
   * You can change the values you need by calling any of the
   * setters on the ITest interface.
   *
   * Note that only one of the three parameters testClass,
   * testConstructor and testMethod will be non-null.
   *
   * @param annotation The annotation that was read from your
   * test class.
   * @param testClass If the annotation was found on a class, this
   * parameter represents this class (null otherwise).
   * @param testConstructor If the annotation was found on a constructor,
   * this parameter represents this constructor (null otherwise).
   * @param testMethod If the annotation was found on a method,
   * this parameter represents this method (null otherwise).
   */

 
public void transform(ITest annotation, Class testClass,
     
Constructor testConstructor, Method testMethod);
}

像其他的TestNG 监听器,你可以指定在命令行或者通过ant来指定这个类:

  java org.testng.TestNG -listener MyTransformer testng.xml

或者在程序中:

  TestNG tng = new TestNG();
  tng
.setAnnotationTransformer(new MyTransformer());
 
// ...

当调用 transform() 的时候,你可以调用任何在 ITest test 参数中的设置方法来在进一步处理之前改变它的值。

例如,这里是你如何覆盖属性 invocationCount 的值,但是只有测试类中的invoke() 方法受影响:

  public class MyTransformer implements IAnnotationTransformer {
   
public void transform(ITest annotation, Class testClass,
       
Constructor testConstructor, Method testMethod)
   
{
     
if ("invoke".equals(testMethod.getName())) {
        annotation
.setInvocationCount(5);
     
}
   
}
 
}

IAnnotationTransformer 只允许你修改一个 @Test 注解。如果你需要修改其他的(假设说配置注解@Factory 或 @DataProvider),使用 IAnnotationTransformer2。

5.16 - 方法拦截器

一旦TestNG 计算好了测试方法会以怎样的顺序调用,那么这些方法就会分为两组:

  • 按照顺序运行的方法。这里所有的方法都有相关的依赖,并且所有这些方法按照特定顺序运行。
  • 不定顺序运行的方法。这里的方法不属于第一个类别。方法的运行顺序是随机的,下一个说不准是什么(尽管如此,默认情况下TestNG会尝试通过类来组织方法)。

为了能够让你更好的控制第二种类别,TestNG定义如下接口:

public interface IMethodInterceptor {
 
 
List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context);

}

方法中叫做methods的那个列表参数包含了所有以不定序运行的方法。你的 intercept 方法也要返回一个 IMethodInstance列表,它可能是下面情况之一:

  • 内容与参数中接收的一致,但是顺序不同
  • 一组 IMethodInstance 对象
  • 更大的一组 IMethodInstance 对象

一旦你定义了拦截器,就把它传递个TestNG,用下面的方式:

java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor /
 -testclass test.methodinterceptors.FooTest

关于 ant 中对应的语法,参见 listeners 属性 ant 文档 中的说明。

例如,下面是个方法拦截器会重新给方法排序,一遍“fast”组中的方法总是先执行:

public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
 
List<IMethodInstance> result = new ArrayList<IMethodInstance>();
 
for (IMethodInstance m : methods) {
   
Test test = m.getMethod().getMethod().getAnnotation(Test.class);
   
Set<String> groups = new HashSet<String>();
   
for (String group : test.groups()) {
      groups
.add(group);
   
}
   
if (groups.contains("fast")) {
      result
.add(0, m);
   
}
   
else {
      result
.add(m);
   
}
 
}
 
return result;
}

5.17 - 从JavaDoc 注解迁移到JDK 注解

如果项目伊始使用了javadoc annotations,但是之后要转换到JDK annotations,这样需要把所有这些都进行转换。

TestNG 提供了一个工具来帮你做这些。

 

java org.testng.AnnotationConverter -srcdir directory [-overwrite|-d destdir] [-quiet]

上述命令会把源文件从一个格式转换到另外一个。如果不带参数运行,就会显示所有参数的用法。

注意,转换后的文件,可能不是非常漂亮,所以要检查一下其正确性。所以最好用版本控制工具,如果不喜欢可以撤销操作!转换器本身也假设你使用了上面 所推荐的语法规约。

5.18 - TestNG 监听器

有很多接口可以用来修改 TestNG 的行为。这些接口都被统称为 "TestNG 监听器"。下面是目前支持的监听器的列表:

  • IAnnotationTransformer (doc, javadoc)
  • IReporter (doc, javadoc)
  • ITestListener (doc, javadoc)
  • IMethodInterceptor (doc, javadoc)
  • IInvokedMethodListener (doc, javadoc)

当你实现了这些接口,你可以让 TestNG 知道这些接口,有如下方式:

  • 在命令行下使用 -listener
  • ant中使用 <listeners>
  • 在 testng.xml 中使用 <listeners> 标签

下面是第三种方式的例子:

<suite>

<listeners>
 
<listener class-name="com.example.MyListener" />
 
<listener class-name="com.example.MyMethodInterceptor" />
</listeners>

...

5.19 - 依赖注入

TestNG 允许你在自己的方法中声明额外的参数。这时,TestNG会自动使用正确的值填充这些参数。依赖注入就使用在这种地方:

  • 任何 @Before 或 @Test 方法可以声明一个类型为 ITestContext 的参数。
  • 任何 @After 都可以声明一个类型为 ITestResult 的单数,它代表了刚刚运行的测试方法。
  • 任何 @Before 和 @After 方法都能够声明类型为 XmlTest 的参数,它包含了当前的 <test> 参数。
  • 任何 @BeforeMethod 可以声明一个类型为 java.lang.reflect.Method 的参数。这个参数会接收 @BeforeMethod 完成调用的时候马上就被调用的那个测试方法当做它的值。
  • 任何 @BeforeMethod 可以声明一个类型为 Object[] 的参数。这个参数会包含要被填充到下一个测试方法中的参数的列表,它既可以又 TestNG 注入,例如 java.lang.reflect.Method 或者来自 @DataProvider。
  • 任何 @DataProvider 可以声明一个类型为 ITestContext 或 java.lang.reflect.Method 的参数。后一种类型的参数,会收到即将调用的方法作为它的值。

5.20 - 监听方法调用

无论何时TestNG即将调用一个测试(被@Test注解的)或者配置(任何使用 @Before or @After 注解标注的方法),监听器 IInvokedMethodListener 都可以让你得到通知。你所要做的就是实现如下接口:

public interface IInvokedMethodListener extends ITestNGListener {
 
void beforeInvocation(IInvokedMethod method, ITestResult testResult);
 
void afterInvocation(IInvokedMethod method, ITestResult testResult);
}

并且就像在 关于TestNG监听器一节 中所讨论的那样,将其声明为一个监听器。

你可能感兴趣的:(测试,文档,javadoc,Constructor,Annotations,methods)