Java 如何根据条件禁用TestNG测试

Java 如何根据条件禁用TestNG测试,java,eclipse,annotations,testng,java-5,Java,Eclipse,Annotations,Testng,Java 5,当前是否有一种方法可以基于某个条件禁用TestNG测试 我知道您目前可以在TestNG中禁用测试: @Test(enabled=false, group={"blah"}) public void testCurrency(){ ... } 我想根据条件禁用相同的测试,但不知道如何禁用。大概是这样的: @Test(enabled={isUk() ? false : true), group={"blah"}) public void testCurrency(){ ... } @Before

当前是否有一种方法可以基于某个条件禁用TestNG测试

我知道您目前可以在TestNG中禁用测试:

@Test(enabled=false, group={"blah"})
public void testCurrency(){
...
}
我想根据条件禁用相同的测试,但不知道如何禁用。大概是这样的:

@Test(enabled={isUk() ? false : true), group={"blah"})
public void testCurrency(){
...
}
@BeforeMethod
protected void checkEnvironment() {
  if (!resourceAvailable) {
    throw new SkipException("Skipping tests because resource was not available.");
  }
}
任何人都知道这是否可行。

你有两个选择:

  • 实施一项计划
  • 使用

注释转换器将测试该条件,然后覆盖@test注释以添加属性“enabled=false”(如果条件不满足)。

一个更简单的选项是在检查条件的方法上使用@BeforeMethod注释。如果你想跳过测试,那就抛出一个。像这样:

@Test(enabled={isUk() ? false : true), group={"blah"})
public void testCurrency(){
...
}
@BeforeMethod
protected void checkEnvironment() {
  if (!resourceAvailable) {
    throw new SkipException("Skipping tests because resource was not available.");
  }
}

我知道有两种方法允许您控制TestNG中的“禁用”测试

需要注意的一个重要区别是,SkipException将中断所有后续测试,同时实现IAnnotationTransformer将根据指定的条件使用反射取消单个测试。我将解释SkipException和iNotationTransformer

跳过异常示例

import org.testng.*;
import org.testng.annotations.*;

public class TestSuite
{
    // You set this however you like.
    boolean myCondition;
    
    // Execute before each test is run
    @BeforeMethod
    public void before(Method methodName){
        // check condition, note once you condition is met the rest of the tests will be skipped as well
        if(myCondition)
            throw new SkipException();
    }
    
    @Test(priority = 1)
    public void test1(){}
    
    @Test(priority = 2)
    public void test2(){}
    
    @Test(priority = 3)
    public void test3(){}
}
i注释变压器示例

import org.testng.*;
import org.testng.annotations.*;

public class TestSuite
{
    // You set this however you like.
    boolean myCondition;
    
    // Execute before each test is run
    @BeforeMethod
    public void before(Method methodName){
        // check condition, note once you condition is met the rest of the tests will be skipped as well
        if(myCondition)
            throw new SkipException();
    }
    
    @Test(priority = 1)
    public void test1(){}
    
    @Test(priority = 2)
    public void test2(){}
    
    @Test(priority = 3)
    public void test3(){}
}
有点复杂,但背后的想法是一个被称为反射的概念

维基-

首先实现IAnnotation接口,将其保存在*.java文件中

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;

public class Transformer implements IAnnotationTransformer {

    // Do not worry about calling this method as testNG calls it behind the scenes before EVERY method (or test).
    // It will disable single tests, not the entire suite like SkipException
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod){

        // If we have chose not to run this test then disable it.
        if (disableMe()){
            annotation.setEnabled(false);
        }
    }

    // logic YOU control
    private boolean disableMe() {
    }
}
然后在测试套件java文件中,在@BeforeClass函数中执行以下操作

import org.testng.*;
import org.testng.annotations.*;

/* Execute before the tests run. */    
@BeforeClass
public void before(){

    TestNG testNG = new TestNG();
    testNG.setAnnotationTransformer(new Transformer());
}

@Test(priority = 1)
public void test1(){}

@Test(priority = 2)
public void test2(){}

@Test(priority = 3)
public void test3(){}
最后一步是确保在build.xml文件中添加侦听器。 我的结果是这样的,这只是build.xml中的一行:

<testng classpath="${test.classpath}:${build.dir}" outputdir="${report.dir}" 
    haltonfailure="false" useDefaultListeners="true"
    listeners="org.uncommons.reportng.HTMLReporter,org.uncommons.reportng.JUnitXMLReporter,Transformer" 
    classpathref="reportnglibs"></testng>

在用
@BeforeMethod
注释的方法中抛出
SkipException
对我不起作用,因为它跳过了我的测试套件的所有剩余测试,而不管这些测试是否抛出了
SkipException

我没有彻底调查它,但我找到了另一种方法:使用
@Test
注释上的
dependsOnMethods
属性:

import org.testng.SkipException;
import org.testng.annotations.Test;

public class MyTest {

  private boolean conditionX = true;
  private boolean conditionY = false;

  @Test
  public void isConditionX(){
    if(!conditionX){
      throw new SkipException("skipped because of X is false");
    }
  }

  @Test
  public void isConditionY(){
    if(!conditionY){
      throw new SkipException("skipped because of Y is false");
    }
  }

  @Test(dependsOnMethods="isConditionX")
  public void test1(){

  }

  @Test(dependsOnMethods="isConditionY")
  public void test2(){

  }
}

第三个选项也可以是 -当假设失败时,TestNG将被指示忽略测试用例,因此不会执行它

  • 使用@Association注释
  • 使用AssumptionListener使用假定.AssumeThit(…) 方法

您可以使用以下示例:

SkipException:如果类中只有一个@Test方法,那么它很有用。与数据驱动框架一样,我只有一种测试方法,需要根据某些条件执行或跳过。因此,我将检查条件的逻辑放在@Test方法中,并获得期望的结果。
它帮助我获得测试用例结果为“通过/失败”和“特定跳过”的数据块报告。

我更喜欢这种基于注释的方法来禁用/跳过基于环境设置的一些测试。易于维护,不需要任何特殊的编码技术

  • 使用IInvokedMethodListener接口
  • 创建自定义注释,例如:@SkipinHeadlesMode
  • 抛出SkipException
public类ConditionalSkipTestAnalyzer实现IInvokedMethodListener{
受保护的静态属性Handler properties=新属性Handler();
@凌驾
调用前公共无效(IInvokedMethod invokedMethod,ITestResult){
方法Method=result.getMethod().getconstructormethod().getMethod();
if(方法==null){
返回;
}
if(方法isAnnotationPresent(SkipInHeadlesMode.class)
&&properties.ishadlessMode()){
抛出新的SkipException(“这些测试不应该在无头模式下运行!”);
}
}
@凌驾
调用后公共无效(IInvokedMethod IInvokedMethod,ITestResult ITestResult){
//自动生成
}
}
查看详细信息:

注释不是可执行代码,因此不太可能。您真正想做的是什么?在什么条件下您希望运行或不运行测试?谢谢matt。更多详细信息,请参见下面的cedric答案。谢谢cedric。我想我会喜欢探索“注释转换器”选项。听起来更像是我要找的。再次感谢。我很快就得到了这个变压器的工作示例。但有一件事并不像我想象的那样。我想通过调用annot.setTestName(concatString)动态转换我运行的测试的名称(…至少它在测试结果上的显示方式),其中annot表示方法注释,但返回结果时原始名称不变。还有别的方法吗??希望不要让你感到困惑。你将无法在运行时重写类的行为,Java就是这样设计的。相反,我建议您将决定该名称的逻辑直接放入测试中,以便可以在getTestName()中返回它。这正是我所做的。我认为setTestName(“newName”)是为了更改测试的名称。我理解调用getTestName()是为了根据测试代码中的逻辑获取名称,但是我想通过说annot.setTestName(newName)或annot.setTestName(getTestName()+“\u Modified”)来为测试设置这个新检索到的名称。当测试完成时,它仍然具有原始名称而不是修改后的名称。这可以实现吗?-如果TestA失败,我想禁用TestB。您好,因为6.13抛出SkipException会将状态设置为failed而不是Skipped。请参阅的文档,其中引用了不推荐使用的“@配置注释。这可能解释了所描述的“@BeforeMethod,etc”的行为。
enabled=false
检查是否发生在比BeforeMethod更早的测试阶段?在某些情况下,使用
enabled=false
比使用hook之前的IMHO要好。