基于抽象语法树遍历的代码生成JUnit [英] Code generating JUnit based on Abstract Syntax tree walk

查看:335
本文介绍了基于抽象语法树遍历的代码生成JUnit的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我具有以下类和方法:

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;
  }
}

假设我要生成以下JUnit测试:

Assume I want to generated the following JUnit test:

包生成;

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));
    }
} 

给出以下树遍历Java语法树的方法:
如何在Eclipse之外的项目中使用Java Eclipse抽象语法树? (即不是eclipse插件)

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?

推荐答案

您需要的不仅仅是解析树。 (几乎没有构建严肃的程序分析工具的每个人都会重复此错误;您需要更多的机器来做真正有趣的事情。这就是为什么编译器并不容易的原因。)

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).

最简单的情况要求将要测试的方法的代码解析为AST,名称/类型解析所有内容,以便您了解所有符号的含义(必须知道val为整数),并确定代码中的控制流以及控制它们的谓词。

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.

利用这些信息,您可以从本质上枚举有效的控制流路径,获取有关控制流的信息。沿着每个路径的谓词,实质上形成了沿着该路径的所有条件的合集。 (在您的示例中,如果.. val%2 ...返回true; 是一条路径,由 val%2 == true 控制)。您会担心建模路径中的副作用如何影响各种谓词。并且您希望将信息的范围设置为整数(以及字符串和数组的大小等)。

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.).

然后,对于每个路径,您需要生成一组输入使路径谓词为真的参数;鉴于该谓词可能非常复杂,因此您可能需要某种 SAT求解器。使用路径谓词的解决方案,您现在需要生成与测试相对应的AST(例如,设置变量以使方法参数能够满足谓词;对于简单的整数方程,您可能只需像在您的示例中那样为参数生成表达式即可)例)。最后,将测试调用组合成一个方法的AST,插入代表一个单元测试用例方法的AST,并漂亮地打印结果。

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 :-}

我们的 DMS软件再造工具包具有 Java前端,它将解析Java ,生成AST,通过一种方法枚举控制流路径[这并不那么容易:考虑例外情况],计算整数变量的范围约束,并为您提供围绕AST进行提取/构造所需内容的一般能力。尚未包含SAT解算器,但我们已经考虑过了。

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.

这篇关于基于抽象语法树遍历的代码生成JUnit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆