我们希望从Spock测试中排除一组特定的测试类,具体取决于是否设置了某些系统属性。现在我们得到了一些代码:
runner {
// skip all slow tests automatically unless test.include.slow=true
if (!Boolean.getBoolean('test.include.slow')) { exclude Slow }
// skip all api tests unless test.include.api=true
if (!Boolean.getBoolean('test.include.api')) { exclude ApiTest }
}
在我们的SpockConfig.groovy中。问题是,第二次排除调用实际上会覆盖第一次调用中定义的排除。我们还尝试构建一个类数组,并将其处理为exclude函数,如下所示:
runner {
Class[] toExclude = []
// skip all slow tests automatically unless test.include.slow=true
if (!Boolean.getBoolean('test.include.slow')) { toExclude << Slow }
// skip all api tests unless test.include.api=true
if (!Boolean.getBoolean('test.include.api')) { toExclude << ApiTest }
exclude toExclude
}
然而,这产生了非常奇怪的例外:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.junit4.IdeaSuite.getDescription(IdeaSuite.java:55)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:43)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: groovy.lang.MissingMethodException: No signature of method: SpockConfig.runner() is applicable for argument types: (SpockConfig$_run_closure1) values: [SpockConfig$_run_closure1@66d33a32]
Possible solutions: run(), run(), run(java.io.File, [Ljava.lang.String;), use([Ljava.lang.Object;)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at SpockConfig.run(SpockConfig.groovy:4)
at org.spockframework.builder.DelegatingScriptBlueprint.evaluate(DelegatingScriptBlueprint.java:33)
at org.spockframework.builder.Sculpturer.$form(Sculpturer.java:32)
at org.spockframework.builder.GestaltBuilder.build(GestaltBuilder.java:19)
at org.spockframework.runtime.ConfigurationBuilder.build(ConfigurationBuilder.java:30)
at org.spockframework.runtime.RunContext.<init>(RunContext.java:54)
at org.spockframework.runtime.RunContext.createBottomContext(RunContext.java:150)
at org.spockframework.runtime.RunContext.get(RunContext.java:130)
at org.spockframework.runtime.Sputnik.runExtensionsIfNecessary(Sputnik.java:86)
at org.spockframework.runtime.Sputnik.getDescription(Sputnik.java:55)
at org.junit.runners.Suite.describeChild(Suite.java:123)
at com.intellij.junit4.IdeaSuite.describeChild(IdeaSuite.java:68)
at com.intellij.junit4.IdeaSuite.getChildren(IdeaSuite.java:85)
at org.junit.runners.ParentRunner.getFilteredChildren(ParentRunner.java:351)
那么在SpockConfig.groovy中处理此类排除的正确方法是什么?
答案 0 :(得分:3)
好的,我们找到了一些解决方案:
runner {
// skip all slow tests automatically unless test.include.slow=true
if (!Boolean.getBoolean('test.include.slow')) { exclude.annotations << Slow }
// skip all api tests unless test.include.api=true
if (!Boolean.getBoolean('test.include.api')) { exclude.annotations << ApiTest }
}
仍然想知道这是正确的方式还是只是一些糟糕的黑客。
答案 1 :(得分:1)
Spock现在有@IgnoreIf
注释来完成这个。
在您要排除的每个测试上方,您可以注释条件,包括系统属性,环境变量和Java版本信息。
@IgnoreIf({ !Boolean.valueOf(properties['test.include.slow']) })
def "run spec if Java system property 'test.include.slow' is true"() {
expect:
true
}
答案 2 :(得分:0)
Spock支持JUnit测试规则,它可以提供一种非常干净的方法。例如,您的功能可以使用注释来指定运行时间:
@SlowTest
def "run spec if Java system property 'test.include.slow' is true"() {
expect:
true
}
@ApiTest
def "run spec if Java system property 'test.include.api' is true"() {
expect:
true
}
首先,您需要创建注释:
<强> SlowTest.java 强>:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SlowTest {
}
<强> ApiTest.java 强>:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiTest {
}
接下来,创建测试规则:
<强> AnnotationsTestRule.java 强>:
public class AnnotationsTestRule implements TestRule {
private final boolean mApiTest;
private final boolean mSlowTest;
public AnnotationsTestRule() {
mApiTest = Boolean.getBoolean("test.include.api")
mSlowTest = Boolean.getBoolean("test.include.slow")
}
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
if (description.getAnnotation(ApiTest.class) != null && !mApiTest || description.getAnnotation(SlowTest.class) != null && !mSlowTest) {
//Skip test when the annotation is present but not the correlating system property
return;
}
base.evaluate();
}
}
}
}
最后,在每个需要此功能的功能上添加本答案第一部分中提到的注释。对于使用这些规范的规范,您还需要声明测试规则。您只需将此行添加到groovy文件即可完成此操作:
@Rule AnnotationsTestRule mAnnotationsTestRule