我希望根据我用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读取我的自定义注释并检查是否应该运行测试。
答案 0 :(得分: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;
}
}
答案 1 :(得分: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 {
...
}
答案 2 :(得分:2)
到目前为止,我发现的最佳选择是通过JUnit Rule。有一个link to GitHub有一个可以使用的文件
答案 3 :(得分:1)
这正是JUnit类别(参见此short introduction)的用途。
使用适当的类别(使用@Category)标记所有测试后,您可以创建运行所有测试的套件,但是创建错误类别的套件或具有正确类别的所有测试。 (使用@IncludeCategory和@ExcludeCategory,您可以将它们组合起来缩小您的选择范围)
类别可用于Suite,Test-class甚至Test-Method级别。
以下是有关JUnit Categories
的更多信息