10

我希望根据我用 Java 创建的自定义注释执行我的 JUnit4 测试。这个自定义注解的目的是让 JUnit4 注意到只有当机器的平台与注解中指定的平台匹配时才应该运行测试。

假设我有以下注释:

public @interface Annotations {
    String OS();
    ...
}

以及以下测试:

public class myTests{

    @BeforeClass
    public setUp() { ... }

    @Annotations(OS="mac")
    @Test
    public myTest1() { ... }

    @Annotations(OS="windows")
    @Test
    public myTest2() { ... }

    @Annotation(OS="unix")
    @Test
    public myTest3() { ... }

}

如果我要在 Mac 机器上执行这些测试,那么只有 myTest1() 应该被执行,其余的应该被忽略。但是,我目前坚持如何实现这一点。如何让 JUnit 读取我的自定义注释并检查是否应该运行测试。

4

5 回答 5

14

您可以使用类别,也可以实现自己的自定义 JUnit 运行器。扩展默认的 JUnit 运行器非常简单,并且允许您定义要以您可能想要的任何方式运行的测试列表。这包括仅查找具有特定注释的那些测试方法。我在下面包含代码示例,您可以将它们用作您自己实现的基础:

注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
   String OS();
}

自定义跑步者类:

public class MyCustomTestRunner extends BlockJUnit4ClassRunner {

   public MyCustomTestRunner(final Class<?> klass) throws InitializationError {
      super(klass);
   }

   @Override
   protected List<FrameworkMethod> computeTestMethods() {
      // First, get the base list of tests
      final List<FrameworkMethod> allMethods = getTestClass()
            .getAnnotatedMethods(Test.class);
      if (allMethods == null || allMethods.size() == 0)
         return allMethods;

      // Filter the list down
      final List<FrameworkMethod> filteredMethods = new ArrayList<FrameworkMethod>(
            allMethods.size());
      for (final FrameworkMethod method : allMethods) {
         final MyCustomAnnotation customAnnotation = method
               .getAnnotation(MyCustomAnnotation.class);
         if (customAnnotation != null) {
            // Add to accepted test methods, if matching criteria met
            // For example `if(currentOs.equals(customAnnotation.OS()))`
            filteredMethods.add(method);
         } else {
            // If test method doesnt have the custom annotation, either add it to
            // the accepted methods, or not, depending on what the 'default' behavior
            // should be
            filteredMethods.add(method);
         }
      }

      return filteredMethods;
   }
}

样本测试类:

@RunWith(MyCustomTestRunner.class)
public class MyCustomTest {
   public MyCustomTest() {
      super();
   }

   @Test
   @MyCustomAnnotation(OS = "Mac")
   public void testCustomViaAnnotation() {
      return;
   }
}
于 2012-11-27T18:29:39.590 回答
6

我发现完全具有这种行为并将它们作为报告中的意识跳过测试的最佳方法是使用您自己的跑步者(如在 AlexR 的答案中)但覆盖 runChild 方法,该方法允许选择测试但像处理忽略而不是完全排除。

要使用的注解

@Retention(RetentionPolicy.RUNTIME)
public @interface TargetOS {
    String family();

    String name() default "";

    String arch() default "";

    String version() default "";
}

JUnit 跑步者

public class OSSensitiveRunner extends BlockJUnit4ClassRunner {
    public OSSensitiveRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        Description description = describeChild(method);
        if (method.getAnnotation(Ignore.class) != null) {
            notifier.fireTestIgnored(description);
        } else if (method.getAnnotation(TargetOS.class) != null) {
            final TargetOS tos = method.getAnnotation(TargetOS.class);
            String name = tos.name().equals("") ? null : tos.name();
            String arch = tos.arch().equals("") ? null : tos.arch();
            String version = tos.version().equals("") ? null : tos.version();
            if (OS.isOs(tos.family(), name, arch, version)) {
                runLeaf(methodBlock(method), description, notifier);
            } else {
                notifier.fireTestIgnored(description);
            }
        } else {
            runLeaf(methodBlock(method), description, notifier);
        }
    }
}

测试中的使用

@RunWith(OSSensitiveRunner.class)
public class SeleniumDownloadHelperTest {
...

并限制特定方法

@Test
@TargetOS(family = "windows")
public void testGetFileFromUrlInternetExplorer() throws Exception {
    ...
}
于 2014-06-14T15:35:30.227 回答
2

到目前为止,我发现的最佳选择是通过JUnit Rule。有一个指向 GitHub 的链接, 其中包含一个可立即使用的文件

于 2015-05-26T14:29:36.787 回答
1

这正是 JUnit 类别(请参阅此简短介绍)的用途。

在使用适当的类别(使用@Category)标记所有测试之后,您可以创建运行所有测试但类别错误的测试或所有具有正确类别的测试的套件。(使用@IncludeCategory 和@ExcludeCategory,您可以将它们组合起来以缩小您的选择范围)

类别可用于套件、测试类甚至测试方法级别。

以下是有关JUnit 类别的更多信息

于 2017-04-11T17:18:31.033 回答
0

您可以使用此注释来启用和禁用测试方法@DisabledOnOs(OS.LINUX)@EnabledOnOs({OS.WINDOWS, OS.MAC})

于 2022-01-01T16:27:45.010 回答