ANTLR and Stringtemplate instances: Generating unit Test classes automatically

Source: Internet
Author: User

ANTLR and Stringtemplate instances: Automatic generation of Unit test Class 1. ANTLR syntax

To automatically generate unit tests, the first step is to analyze the class being tested. Here is an example of Java code, using ANTLR to analyze Java code. It is hard to imagine the complexity of a ANTLR grammar file that is completely handwritten by itself, and it is very thoughtful to have a lot of common language grammar files listed on the ANTLR GitHub website, such as SQL syntax for Java,sqlite and MySQL.

With the. G4 syntax file, you can automatically generate the parser code by following the steps in the ANTLR V4 Introductory tutorial and the example, which is no longer detailed.

2. Stringtemplate Foundation

Stringtemplate (referred to as St) is also a very useful tool provided by ANTLR. It functions like velocity, freemaker, and other template engines, and can render different Web pages, messages, code, and so on at run time according to different values according to predefined templates. But as you can see from the string in the name, it's relatively lightweight. Try it. This is true, supporting hard-coded templates in Java.

But the trial process still encountered a lot of problems, always feel its template syntax is a bit complex ah! And the latest ST4 API has changed a lot from the previous version, and many of the examples on the web are not useful. Specifically, refer to the official website of the tutorial, as well as this cheatsheet form. Of course, there is a lot of time to debug the code sample of this article!

3. Unit Test Generator

First look at the main method. The input text is a Java class represented by the code variable, which has two methods. Then use the automatically generated ANTLR code to construct the processing chain of the semantic parser and parser, and pass UnitTestGenerator in the listener to traverse the input text.

 Public  class javacodeparsetest {     Public Static void Main(string[] args) {String Code ="Package com.jcache.store;"+"public class Cachestore {"+"Object getcache (int a) {"+"if (a = = 1)"+"return 1;"+"Else"+"return 2;"+"}"+"void Setcache (int a) {"+"return;"+"}"+"}";//1.Lexical AnalysisJavalexer lexer =NewJavalexer (NewAntlrinputstream (code)); Commontokenstream tokens =NewCommontokenstream (lexer);//2.Syntax AnalysisJavaparser parser =NewJavaparser (tokens); Parsetree tree = Parser.compilationunit ();//3.Application based on Syntax TreeParsetreewalker Walker =NewParsetreewalker (); Walker.walk (NewUnittestgenerator (), tree); }}

Here's a look UnitTestGenerator at the implementation of a core code.
A few key points in the code are briefly described here:

    • St Template group: In the template file definition is relatively simple, if you want to define a template in Java, you must refer to this example static initialization block notation.
    • Nested templates and multi-valued: To automatically generate a method for each method name based on the list of method names, you need to follow
/** * Simple Unit Test Generator. * * Public  class unittestgenerator extends javabaselistener {    /** constants:template name, placeholder name, generated code name * /    Private Static FinalString Class_st_name ="Classst";Private Static FinalString Method_st_name ="METHODST";Private Static FinalString Test_pkg_name ="Testpkgname";Private Static FinalString Test_class_name ="Testclassname";Private Static FinalString Test_method_name ="Testmethodname";Private Static FinalString Class_name_suffix ="Test";Private Static FinalString Method_name_prefix ="Test";/** Template for Java * /    Private Static FinalString Method_st = t ("@Test") + t ("public void"+ $ (test_method_name) +"() throws Exception {") + TT ("//body ...") + t ("}") + N ("");Private Static FinalString Class_st = N ("Package"+ $ (test_pkg_name) +";") + N ("") + N ("Import org.junit.*;") + N ("") + N ("public class"+ $ (test_class_name) +" {") + N ("") +/** * Apply nested template ' methodst ' to multi-valued attributes ' Testmethodname '. * Note: <attribute:template (argument-list) > * Apply template to attribute with optional Argument-li             St.             * Example: <name:bold () > Applies bold () to name ' s value.             * The first argument of the template gets the iterated value. */N ($ (test_method_name +":"+ Method_st_name +" (); separator=\" \n\ "")) + N ("}");/** ST Group to nest template * /    Private StaticStgroup Group;Static{Group =NewStgroup (' $ ',' $ ');        COMPILEDST classst = group.definetemplate (Class_st_name, Class_st); Classst.addarg (NewFormalargument (Test_pkg_name)); Classst.addarg (NewFormalargument (Test_class_name)); Classst.addarg (NewFormalargument (Test_method_name));        COMPILEDST METHODST = group.definetemplate (Method_st_name, Method_st); Methodst.addarg (NewFormalargument (Test_method_name)); }/** Attributes. NOTE:group.getInstanceOf () return new ST * *    Privatemap<string, object> AttributeMap =NewHashmap<> ();@Override     Public void enterpackagedeclaration(@NotNull Javaparser.packagedeclarationcontext CTX)    {Attributemap.put (Test_pkg_name, Ctx.qualifiedname (). GetText ()); }@Override     Public void enterclassdeclaration(@NotNull Classdeclarationcontext CTX) {String Orgclassname = ctx.        Identifier (). GetText ();        String testclassname = Orgclassname + class_name_suffix;    Attributemap.put (Test_class_name, testclassname); }@Override     Public void entermethoddeclaration(@NotNull Methoddeclarationcontext CTX) {String Orgmethodname = ctx.        Identifier (). GetText (); String testmethodname = Method_name_prefix + orgmethodname.substring (0,1). toUpperCase () + orgmethodname.substring (1);//multi-valued attributeList<string> methodnames = (list<string>) attributemap.get (test_method_name);if(Methodnames = =NULL) {Methodnames =NewArraylist<> ();        Attributemap.put (Test_method_name, methodnames);    } methodnames.add (Testmethodname); }@Override     Public void enterstatement(@NotNull Statementcontext CTX) {//If/else/switch, For/while, Try-catch        Switch(Ctx.getstart (). GetText ()) { Case "If": Break; Case "for": Break; Case "Try": Break;default: Break; }    }@Override     Public void Exitcompilationunit(@NotNull Javaparser.compilationunitcontext CTX)        {ST template = group.getinstanceof (class_st_name);        Attributemap.entryset (). ForEach (E-Template.add (E.getkey (), E.getvalue ())); System.out.println (Template.render ());//CleanupAttributemap.clear (); }// =======================================    //String Utility    // =======================================    Private StaticString $ (string attrname) {return "$"+ Attrname +"$"; }Private StaticStringN(String str) {returnSTR +"\ n"; }Private StaticStringT(String str) {return "\ T"+ N (str); }Private StaticStringTT(String str) {return "\t\t"+ N (str); }}

ANTLR and Stringtemplate instances: Generating unit Test classes automatically

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.