【问题标题】:The value for annotation attribute Test.enabled must be a constant expression注释属性 Test.enabled 的值必须是常量表达式
【发布时间】:2017-08-28 20:26:29
【问题描述】:

基本上,我想使用我通过反射更改的 Context 类的常量布尔属性,以便我可以动态设置为 TestNG 类中的 testNG 方法启用的@annotated。 TestNG 类具有与 Context.DISBLE_TEST_CASES_IF_OLD_STACK 相同的静态最终属性。我已经为 TestNG 类及其方法粘贴了下面的代码。 我的最终目标是根据上下文切换启用的值或基本上禁用测试,如果它的旧环境或新环境

 package com.abc.api.core.context;

    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;


    public class Context {
        public static final boolean DISBLE_TEST_CASES_IF_OLD_STACK = getConstantReflection();


        public static boolean getConstantReflection()
        {
            System.out.println(DISBLE_TEST_CASES_IF_OLD_STACK);
            try {
                setEnableFlagBasedOnStackForTestCases();
            } catch (NoSuchFieldException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Context.DISBLE_TEST_CASES_IF_OLD_STACK);
            try {
                final Field fld = Context.class.getDeclaredField("DISBLE_TEST_CASES_IF_OLD_STACK");
                return (Boolean) fld.get( null );
            } catch (NoSuchFieldException e) {
                return (Boolean) null;
            } catch (IllegalAccessException e) {
                return (Boolean) null;
            }
        }

        private static void setEnableFlagBasedOnStackForTestCases() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{


            Field f = Context.class.getDeclaredField("DISBLE_TEST_CASES_IF_OLD_STACK");
            f.setAccessible(true);

            //'modifiers' - it is a field of a class called 'Field'. Make it accessible and remove
            //'final' modifier for our 'CONSTANT' field
            Field modifiersField = Field.class.getDeclaredField( "modifiers" );
            modifiersField.setAccessible( true );
            modifiersField.setInt( f, f.getModifiers() & ~Modifier.FINAL );

            if (TestcaseContext.getContext().equalsIgnoreCase(Context.OLD_STACK)) {
                f.setBoolean(null, false);
            }else {
                f.setBoolean(null, true);
            }
        }

    }

测试类和方法示例:

package com.abc.api.test.tests.TestA;

import com.abc.api.core.context.Context;

public class TestA extends TestCommon {

    private static final boolean ENABLE_DISABLE = Context.DISBLE_TEST_CASES_IF_OLD_STACK;

    /**
     * 
     */
    @BeforeTest
    void setPropertiesFile() {
      ......

    }

    /**
     * PATCH Positive Test Cases
     * 
     */

    @Test(priority = 11, enabled=ENABLE_DISABLE)
    public void testPositive1() {
        ......
    }
}

【问题讨论】:

  • 您的DISBLE_TEST_CASES_IF_OLD_STACK 不是一个常量变量。您将无法在注释中使用它。
  • 但是反射本质上不是修改静态最终值,它实际上是类的常量属性。因此,我走过了这条使用反射的道路。
  • 允许编译器直接复制常量变量值,并且在运行时从不实际读取它们,因此即使它编译也不会起作用。参见例如ideone.com/WT9j9z

标签: java reflection testng


【解决方案1】:

为了有选择地禁用测试用例的最终目标,您可以使用 TestNgs IAnnotationTransformer 来控制启用标志。它将在每个@Test 注解的方法之前运行,并且可以控制它的执行。

例如。

public class DemoTransformer implements IAnnotationTransformer {
  public void transform(ITest annotation, Class testClass,
      Constructor testConstructor, Method testMethod)
  {
    if (condition) {
        annotation.setEnabled(false/true);
  }
}

【讨论】:

  • 这正是我最终所做的。但是,由于某种原因,当我用侦听器类注释 TestNG 类时,未调用侦听器。我不得不在测试套件中通过 xml 使用监听器,这有点令人失望,因为我想将此监听器应用于这个特定的类。另外,我发现我可以只使用组并根据需要排除和包含它们。
猜你喜欢
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2013-04-05
  • 2019-07-03
  • 1970-01-01
  • 2013-02-09
相关资源
最近更新 更多