2016-08-03 131 views
2

我正在编写一个库,它依赖于AbstractProcessor类,因为我想写一个伟大的库,我希望它有很好的覆盖率。由于预处理器在编译时工作,我不知道如何测试该代码。测试AbstractProcessor(Java在编译时的注解处理)

我有一些测试场景记住构建应该失败的地方。但是,我如何测试?我必须执行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

请分享您的代码和目前为止编写的测试场景。他们怎么了? –

+0

只是想知道你知道我在说什么吗?这是一个高度复杂的话题,如果你熟悉它,我的问题的抽象层次应该没问题。不过,如果这使得它更清晰,我可以添加一个示例。 – rekire

+0

@RobertColumbia这里是一个简单的示例项目,它不能按预期进行编译:https://github.com/rekire/AnnotationTesting你只需要检查项目并执行'gradlew cJ',如果你使用linux,你必须修复缺少脚本的x权限。 – rekire

回答

1

以前的团队编写的编译器和注释处理器已经解决了这个问题,因此您可以重新使用他们的解决方案。

javac团队使用名为jtreg的工具。 例如,这里是一个jtreg test,它使用不同的命令行参数编译一个源文件6次,为每个参数指定一个不同的expected compiler output

Checker Framework团队专门为注释处理器设计了一个测试框架。这里是使用该框架的test case,其中特别的//::注释表示注释处理器预计发行的线a warningan error

+0

我正在尝试使用该jtreg库,但是我不太了解如何使用它。我将尝试在gradle中调用jtreg,现在我知道我可以运行'java -Dprogram = jtreg -jar/tmp/jtreg/lib/jtreg.jar',但是我需要应用哪些参数?那个'@ Compile'注释是如何开始一个新的编译过程的?我一点都不明白。 – rekire

+0

好吧,我猜我现在管理了,但是我的参考文件不匹配。我如何找出文件的确切格式?只是预期的错误输出? – rekire

+0

是的,jtreg需要编译器输出来匹配目标文件。 jtreg不会尝试巧妙地解析输出。关于如何运行jtreg,我建议看看jtreg文档。 – mernst

1

谷歌有一个很好的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(); 
    } 
}