2009-11-28 17 views
19

मैं जावा एनोटेशन प्रोसेसर के साथ प्रयोग कर रहा हूं। मैं "JavaCompiler" का उपयोग करके एकीकरण परीक्षण लिखने में सक्षम हूं (वास्तव में मैं इस समय "हिकोरी" का उपयोग कर रहा हूं)। मैं संकलन प्रक्रिया चला सकता हूं और आउटपुट का विश्लेषण कर सकता हूं। समस्या: एक एकल परीक्षण मेरे एनोटेशन प्रोसेसर में किसी भी कोड के बिना भी आधा सेकेंड तक चलता है। यह टीडीडी शैली में इसका उपयोग करने के लिए बहुत लंबा तरीका है।जावा एनोटेशन प्रोसेसर के लिए स्वचालित यूनिट परीक्षण कैसे लिखें?

निर्भरताओं को दूर करना मेरे लिए बहुत मुश्किल लगता है (मुझे पूरे "javax.lang.model.element" पैकेज को मजाक करना होगा)। क्या कोई एनोटेशन प्रोसेसर (जावा 6) के लिए यूनिट परीक्षण लिखने में सफल रहा है? यदि नहीं ... आपका दृष्टिकोण क्या होगा?

उत्तर

8

आप एनोटेशन प्रोसेसिंग एपीआई (मॉक लाइब्रेरी जैसे आसान मॉक के साथ) का मज़ाक उड़ा रहे हैं दर्दनाक है। मैंने इस दृष्टिकोण की कोशिश की और यह बहुत तेजी से टूट गया। आपको कई विधि कॉल अपेक्षाओं को सेटअप करना होगा। परीक्षण अनजान हो जाते हैं।

राज्य-आधारित परीक्षण दृष्टिकोण मेरे लिए काफी अच्छा काम करता है। मुझे javax.lang.model.* API I needed for my tests के हिस्सों को लागू करना पड़ा। (यह केवल < कोड की 350 लाइनें थीं।)

यह javax.lang.model ऑब्जेक्ट्स को शुरू करने के लिए एक परीक्षण का हिस्सा है। सेटअप के बाद मॉडल जावा कंपाइलर कार्यान्वयन के समान राज्य में होना चाहिए।

DeclaredType typeArgument = declaredType(classElement("returnTypeName")); 
DeclaredType validReturnType = declaredType(interfaceElement(GENERATOR_TYPE_NAME), typeArgument); 
TypeParameterElement typeParameter = typeParameterElement(); 
ExecutableElement methodExecutableElement = Model.methodExecutableElement(name, validReturnType, typeParameter); 

स्थिर कारखाने तरीकों वर्ग Model javax.lang.model को लागू करने में परिभाषित कर रहे हैं। * क्लासेस। उदाहरण के लिए declaredType। (सभी असमर्थित आपरेशन अपवाद फेंक देते हैं।)

public static DeclaredType declaredType(final Element element, final TypeMirror... argumentTypes) { 
    return new DeclaredType(){ 
     @Override public Element asElement() { 
      return element; 
     } 
     @Override public List<? extends TypeMirror> getTypeArguments() { 
      return Arrays.asList(argumentTypes); 
     } 
     @Override public String toString() { 
      return format("DeclareTypeModel[element=%s, argumentTypes=%s]", 
        element, Arrays.toString(argumentTypes)); 
     } 
     @Override public <R, P> R accept(TypeVisitor<R, P> v, P p) { 
      return v.visitDeclared(this, p); 
     } 
     @Override public boolean equals(Object obj) { throw new UnsupportedOperationException(); } 
     @Override public int hashCode() { throw new UnsupportedOperationException(); } 

     @Override public TypeKind getKind() { throw new UnsupportedOperationException(); } 
     @Override public TypeMirror getEnclosingType() { throw new UnsupportedOperationException(); } 
    }; 
} 

परीक्षण के बाकी परीक्षण के अंतर्गत वर्ग के व्यवहार की पुष्टि करता है।

Method actual = new Method(environment(), methodExecutableElement); 
Method expected = new Method(..); 
assertEquals(expected, actual); 

आप source code of the Quickcheck @Samples and @Iterables source code generator tests पर एक नज़र डाल सकते हैं। (कोड इष्टतम नहीं है। विधि वर्ग में कई पैरामीटर हैं और पैरामीटर वर्ग का परीक्षण अपने परीक्षण में नहीं किया जाता है, लेकिन विधि परीक्षण के हिस्से के रूप में। इसे फिर भी दृष्टिकोण को स्पष्ट करना चाहिए।)

वीएल ग्लूक!

0

एक विकल्प एक वर्ग में सभी परीक्षणों को बंडल करना एक विकल्प है। संकलन आदि के लिए आधा सेकेंड परीक्षण के दिए गए सेट के लिए निरंतर है, परीक्षण के लिए वास्तविक परीक्षण समय नगण्य है, मुझे लगता है।

0

मैंने http://hg.netbeans.org/core-main/raw-file/default/openide.util.lookup/test/unit/src/org/openide/util/test/AnnotationProcessorTestUtils.java का उपयोग किया है, हालांकि यह सादगी के लिए java.io.File पर आधारित है और इस प्रकार प्रदर्शन ओवरहेड के बारे में आप शिकायत करते हैं।

पूरे जेएसआर 26 9 पर्यावरण का मज़ाक उड़ाते हुए थॉमस के सुझाव से शुद्ध इकाई परीक्षण होगा। आप इसके बजाय अधिक एकीकरण परीक्षण लिखना चाहते हैं जो जांचता है कि आपका प्रोसेसर वास्तव में जावैक के अंदर कैसे चलता है, और अधिक आश्वासन देता है कि यह सही है, लेकिन केवल डिस्क फ़ाइलों से बचना चाहता है। ऐसा करने के लिए आपको एक नकली JavaFileManager लिखना होगा, जो दुर्भाग्य से ऐसा लगता है जितना आसान लगता है और मेरे पास कोई उदाहरण आसान नहीं है, लेकिन आपको अन्य चीजों जैसे Element इंटरफेस की नकल करने की आवश्यकता नहीं है।

35

यह एक पुराना सवाल है, लेकिन ऐसा लगता है कि एनोटेशन प्रोसेसर परीक्षण की स्थिति किसी भी बेहतर नहीं हुई है, इसलिए हमने आज Compile Testing जारी किया। सबसे अच्छे दस्तावेज़ package-info.java में हैं, लेकिन सामान्य विचार यह है कि एनोटेशन प्रोसेसर के साथ चलते समय संकलन आउटपुट का परीक्षण करने के लिए एक धाराप्रवाह API है।उदाहरण के लिए,

ASSERT.about(javaSource()) 
    .that(JavaFileObjects.forResource("HelloWorld.java")) 
    .processedWith(new MyAnnotationProcessor()) 
    .compilesWithoutError() 
    .and().generatesSources(JavaFileObjects.forResource("GeneratedHelloWorld.java")); 

परीक्षण है कि प्रोसेसर है कि (वर्ग पथ पर सुनहरा फ़ाइल) GeneratedHelloWorld.java से मेल खाता है एक फाइल उत्पन्न करता है। तुम भी परीक्षण कर सकते हैं कि प्रोसेसर त्रुटि उत्पादन का उत्पादन:

JavaFileObject fileObject = JavaFileObjects.forResource("HelloWorld.java"); 
ASSERT.about(javaSource()) 
    .that(fileObject) 
    .processedWith(new NoHelloWorld()) 
    .failsToCompile() 
    .withErrorContaining("No types named HelloWorld!").in(fileObject).onLine(23).atColumn(5); 

यह स्पष्ट रूप से मजाक से और ठेठ एकीकरण परीक्षणों के विपरीत बहुत आसान है, उत्पादन के सभी स्मृति में संग्रहीत किया जाता है।

0

मैं इसी तरह की स्थिति में था, इसलिए मैंने Avatar लाइब्रेरी बनाई। यह आपको किसी भी संकलन के साथ शुद्ध इकाई परीक्षण का प्रदर्शन नहीं देगा, लेकिन यदि सही तरीके से उपयोग किया जाता है तो आपको प्रदर्शन प्रदर्शन में अधिकतर दिखाई नहीं देनी चाहिए।

अवतार आपको एक स्रोत फ़ाइल लिखने, इसे एनोटेट करने और यूनिट परीक्षण में तत्वों में परिवर्तित करने देता है। यह आपको यूनिट परीक्षण विधियों और कक्षाओं की अनुमति देता है जो मैन्युअल रूप से जैवैक का आविष्कार किए बिना एलिमेंट ऑब्जेक्ट्स का उपभोग करते हैं।

संबंधित मुद्दे