Code generating JUnit based on Abstract Syntax tre

2019-05-24 21:29发布

Assuming I have the following class and method:

package generation;

class HelloWorld {
  public boolean isEven(int val) {
    if ( (val % 2) == 0)
      return true;
    else
      return false;
  }
}

Assume I want to generated the following JUnit test:

package generation;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class HelloWorldTest {

    @Test
    public void testIsEven() {
        HelloWorld h = new HelloWorld();
        assertTrue(h.isEven(2));
        assertFalse(h.isEven(1));
    }
} 

Given the following method of tree walking a Java Syntax Tree: How can I use the java Eclipse Abstract Syntax Tree in a project outside Eclipse? (ie not an eclipse plugin)

How would you code generate the Unit test case given the class example up the top?

2条回答
Viruses.
2楼-- · 2019-05-24 21:59

You need a lot more than just a parse tree. (This mistake is repeated by practically everybody that hasn't built a serious program analysis tool; you need a lot more machinery to do anything really interesting. It is why compilers aren't trivial).

The "simplest" case requires parsing the code of the method to be tested into ASTs, name/type resolving everything so you know the meaning of all the symbols (you have to know that val in an integer), and determining the control flows through the code, and the predicates that control them.

With that information, you can essentially enumerate valid control-flow paths, picking up information about the predicates along the path for each one, forming in essence a conjunction of all the conditions along that path. (In your example, if .. val%2 ... return true; is one path, controlled by val%2==true). You get to worry about modelling how side effects in the path affect the various predicates. And you'd like to range information on integers (and sizes of strings and arrays, etc.).

Then for each path, you need to generate a set of input arguments that makes the path predicate true; given that this predicate could be pretty complicated, you'll likely need some kind of SAT solver. With solutuions to the path predicate, you now need to generate ASTs corresponding to to tests (e.g., set up variables to enable the method arguments to satisy the predicate; for simple integer equations, you can likely just generate expressions for the arguments as in your example). Finally, assemble the test calls into an AST for a method, insert into an AST representing a unit test case method, and prettyprint the result.

Well, that wasn't so hard :-}

Our DMS Software Reengineering Toolkit has a Java front end that will parse Java, produce ASTs, enumerate control flow paths through a method [this isn't so easy: consider exceptions], compute range constraints on integer variables, and give you the general ability to climb around the ASTs to extract/construct what you want. Doesn't include a SAT solver yet, but we've thought about it.

查看更多
贪生不怕死
3楼-- · 2019-05-24 22:15

You might want to skip the awkward, hardly well-defined part of your questions and look into property based testing.

查看更多
登录 后发表回答