2012-11-27 27 views
9

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

+2

你能不能用[类别]更多的信息(https://github.com/KentBeck/junit/wiki/Categories)? – assylias

回答

11

您既可以使用类别,也可以实现自己的自定义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; 
    } 
} 
+0

我打算发布一个自定义亚军的答案,但看到你提到它时,请介意如果我扩大你的答案,而不是? – Perception

+0

@Perception:请这样做,我想对此有更多的了解。 – user1754960

+0

@AlexR:不确定'categories'是什么意思,请提供一些关于此的更多细节。 对不起,仍然是JUnit和Java的新手。先进的谢谢! – user1754960

4

我发现有这种行为的最好方法,并让他们在报告中跳过对认知的测试,就是使用你自己的跑步者(就像在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 { 
    ... 
} 
0

这正是JUnit类别(请参阅此short introduction)所作的。

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

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

下面是关于JUnit Categories