我正在写一个依赖AbstractProcessor
课程的图书馆,因为我想写一个很棒的图书馆,我也希望有一个很好的报道。由于预处理器在编译时工作,我不知道如何测试该代码。
我有一些测试方案,其中构建应该失败。但是我怎么测试呢?我是否必须执行gradle并检查退出代码?是否有一种干净的方法来验证由预期原因导致的构建失败,还是我还需要编写某种解析器?这将是恕我直言,只是为了获得良好的报道,这是一个巨大的开销。
对于那些需要一个例子的人:
@SupportedAnnotationTypes("eu.rekisoft.java.preprocessor.Decorator")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ExamplePreprocessor extends AbstractProcessor {
public ExamplePreprocessor() {
super();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for(Element elem : roundEnv.getElementsAnnotatedWith(Decorator.class)) {
Method method = Method.from((ExecutableElement)elem);
if(!method.matchesTypes(String.class, StringBuilder.class)) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "No! " + elem + " has the wrong args!");
} else {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Yey " + elem + " this is fine!");
}
}
return true; // no further processing of this annotation type
}
}
这是一个无法编译的类:
public class AnnotationedExample {
@Decorator
public int breakBuild() {
return -1;
}
@Decorator
public String willCompile(StringBuilder sb) {
return null;
}
}
最后是无聊的注释:
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Decorator {
}
您还可以在GitHub结帐项目,只需签出项目并执行gradlew cJ
即可。您可能必须在linux和mac上修复缺少的x权限。
答案 0 :(得分:2)
Google有一个很好的API来测试编译。 (https://github.com/google/compile-testing)。这是一个测试.java文件是否使用junit编译处理器的示例。
package org.coffeebag.processor;
import com.google.testing.compile.JavaFileObjects;
import com.google.testing.compile.JavaSourceSubjectFactory;
import org.junit.Test;
import java.io.File;
import java.net.MalformedURLException;
import static org.truth0.Truth.ASSERT;
public class ExampleTest {
@Test
public void EmptyClassCompiles() throws MalformedURLException {
final MyProcessor processor = MyProcessor.testMode();
File source = new File("path/to/test/file.java");
ASSERT.about(JavaSourceSubjectFactory.javaSource())
.that(JavaFileObjects.forResource(source.toURI().toURL()))
.processedWith(processor)
.compilesWithoutError();
}
}
答案 1 :(得分:1)
以前的团队编写编译器和注释处理器已经解决了这个问题,因此您可以重新使用他们的解决方案。
javac团队使用名为jtreg的工具。 例如,这里有一个jtreg test,它使用不同的命令行参数编译源文件6次,每个参数指示不同的expected compiler output。
Checker Framework团队专门为注释处理器设计了一个测试框架。以下是使用该框架的test case,其中特殊//::
条注释表示注释处理器应在其中发布a warning或an error的行。
答案 2 :(得分:0)
我们编写了一个简化的API,可帮助访问javax.tools.JavaCompiler
API进行内存Java编译,从而可以编写简单的基于JUnit的测试。在您的示例中,您可以编写:
@Test
public void testFailAnnotationProcessing() {
ExamplePreprocessor p = new ExamplePreprocessor();
try {
Reflect.compile(
"com.example.test.FailAnnotationProcessing",
"package com.example.test; " +
"public class FailAnnotationProcessing { " +
" @com.example.Decorator " +
" public int breakBuild() { " +
" return -1; " +
" } " +
"}",
new CompileOptions().processors(p)
).create().get();
Assert.fail();
}
catch (ReflectException expected) {}
}
@Test
public void testSucceedAnnotationProcessing() {
ExamplePreprocessor p = new ExamplePreprocessor();
Reflect.compile(
"com.example.test.SucceedAnnotationProcessing",
"package com.example.test; " +
"public class SucceedAnnotationProcessing { " +
" @com.example.Decorator " +
" public String willCompile(StringBuilder sb) { " +
" return null; " +
" } " +
"}",
new CompileOptions().processors(p)
).create().get();
}