如何根据条件禁用 TestNG 测试

Posted

技术标签:

【中文标题】如何根据条件禁用 TestNG 测试【英文标题】:How to disable TestNG test based on a condition 【发布时间】:2011-04-26 03:17:10 【问题描述】:

目前有没有办法根据条件禁用 TestNG 测试

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

@Test(enabled=false, group="blah")
public void testCurrency()
...

我想根据条件禁用相同的测试,但不知道如何。像这样:

@Test(enabled=isUk() ? false : true), group="blah")
public void testCurrency()
...

任何人都知道这是否可能。

【问题讨论】:

注解不是可执行代码,所以这不太可能。您真正想要做什么 - 您希望在什么条件下运行或不运行测试? 感谢马特。有关详细信息,请参阅下面的 cedrics 答案。 【参考方案1】:

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

@BeforeMethod
protected void checkEnvironment() 
  if (!resourceAvailable) 
    throw new SkipException("Skipping tests because resource was not available.");
  

【讨论】:

您好,从 6.13 开始,抛出 SkipException 会将状态设置为 Failed 而不是 Skipped。见***.com/questions/20022288/… SkipException 的文档指的是已弃用的 '@Configuration 注释。这可能解释了 '@BeforeMethod 等所描述的行为。 enabled=false 检查不是发生在比 BeforeMethod 更早的测试阶段吗?在某些情况下,使用enabled=false 会比使用前挂钩更好,恕我直言。【参考方案2】:

你有两个选择:

实现annotation transformer。 使用BeanShell。

您的注解转换器将测试条件,然后如果条件不满足,则覆盖@Test 注解以添加属性“enabled=false”。

【讨论】:

谢谢塞德里克。我想我想探索“注释转换器”选项。这听起来更像是在寻找什么。 再次感谢。我很快就得到了这个变压器的工作示例。但有一件事并没有像我预期的那样表现。我想通过调用 annot.setTestName(concatString) 来动态转换我运行的测试的名称(...至少它将在测试结果上显示的方式),其中 annot 表示方法注释,但结果返回原始名称不变。还有其他方法可以做到这一点吗?希望没有让你感到困惑。 您将无法在运行时覆盖类的行为,这正是 Java 的设计方式。相反,我建议您将决定该名称的逻辑直接放入测试中,以便您可以在 getTestName() 中返回它。 这正是我所做的。我认为 setTestName("newName") 是为了更改测试的名称。我理解调用 getTestName() 以根据测试代码中的逻辑获取名称,但是我想通过说 annot.setTestName(newName) 或 annot.setTestName(getTestName()+"_Modified") 来设置这个新检索到的测试名称。测试完成后,它仍然具有原始名称,而不是修改后的名称。 这个可以实现吗? - 如果 TestA 失败,我想禁用 TestB【参考方案3】:

据我所知,有两种方法可以让您控制在 TestNG 中“禁用”测试。

需要注意的非常重要的区别是,在实现 IAnnotationTransformer 时,SkipException 将中断所有后续测试,并根据您指定的条件使用反射来禁用单个测试。我将解释 SkipException 和 IAnnotationTransfomer。

跳过异常示例

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()

IAnnotationTransformer 示例

有点复杂,但其背后的想法是一个称为反射的概念。

维基 - http://en.wikipedia.org/wiki/Reflection_(computer_programming)

首先实现 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>

【讨论】:

【参考方案4】:

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

使用@Assumption 注释 使用 AssumptionListener 使用 Assumes.assumeThat(...) 方法

你可以使用这个例子:example

【讨论】:

【参考方案5】:

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

使用 IInvokedMethodListener 接口 创建自定义注释,例如:@SkipInHeadlessMode 抛出 SkipException
public class ConditionalSkipTestAnalyzer implements IInvokedMethodListener 
    protected static PropertiesHandler properties = new PropertiesHandler();

    @Override
    public void beforeInvocation(IInvokedMethod invokedMethod, ITestResult result) 
        Method method = result.getMethod().getConstructorOrMethod().getMethod();
        if (method == null) 
            return;
        
        if (method.isAnnotationPresent(SkipInHeadlessMode.class)
                && properties.isHeadlessMode()) 
            throw new SkipException("These Tests shouldn't be run in HEADLESS mode!");
        
    

    @Override
    public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) 
        //Auto generated
    

查看详情: https://www.lenar.io/skip-testng-tests-based-condition-using-iinvokedmethodlistener/

【讨论】:

【参考方案6】:

在带有 @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()

  

【讨论】:

【参考方案7】:

SkipException:如果我们在类中只有一个 @Test 方法,这很有用。与数据驱动框架一样,我只有一个测试方法需要根据某些条件执行或跳过。因此,我将检查条件的逻辑放在 @Test 方法中并获得所需的结果。 它帮助我获得了测试用例结果为 Pass/Fail 和特定 Skip 的范围报告。

【讨论】:

以上是关于如何根据条件禁用 TestNG 测试的主要内容,如果未能解决你的问题,请参考以下文章

如何根据带有闪亮元素的 R Markdown 文档中的条件禁用按钮?

如何根据条件禁用列表项 - ASP.NET C#

如何根据另一个参数的值有条件地禁用 Storybook 中的控件?

如何根据角度 6 中的条件禁用复选框?

“根据条件在 testNG 中执行测试”

根据条件禁用按钮