JUnit4根据自定义java注释跳过测试

我希望我的JUnit4测试可以根据我用Java创建的自定义注释来执行。 此自定义注释的目的是让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读取我的自定义注释并检查是否应该运行测试。

您可以使用类别,也可以实现自己的自定义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 computeTestMethods() { // First, get the base list of tests final List allMethods = getTestClass() .getAnnotatedMethods(Test.class); if (allMethods == null || allMethods.size() == 0) return allMethods; // Filter the list down final List filteredMethods = new ArrayList( 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; } } 

我发现完全具有这种行为并将它们作为报告中的跳过测试意见的最佳方法是使用您自己的跑步者(如在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 { ... } 

到目前为止,我发现的最佳选择是通过JUnit Rule 。 有一个带有即用型文件的GitHub链接

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

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

类别可用于Suite,Test-class甚至Test-Method级别。

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