【问题标题】:Unit testing when the output is a wall of text当输出是一堵文本墙时的单元测试
【发布时间】:2011-10-10 11:02:29
【问题描述】:

我目前正在测试我的应用程序的一部分(我们假设它是一个名为 X 的类),它以反射 java 方法作为参数,并将基于它打印一些 java 代码(也就是说,它是一个代码生成器)。例如,当将String.toString() 传递给X 时,呈现的字符串输出将是:

public static java.lang.String toString(String thisObj, boolean isMonitoring) {
    String thisObjOld = (String)thisObj.clone(thisObj, false);

    if (isMonitoring) {
        toStringPre(thisObj);
    }

    java.lang.String result = thisObj.toString_Original();

    if (isMonitoring) {
        toStringPost(thisObj, thisObjOld, result);
    }

    return result
}

现在,我想知道如何测试这个输出。我想(单独)测试不同的东西。

我知道最完美的做法是在印刷之前对抽象表示进行断言,而不是在最终文本中。但不幸的是,设置起来似乎工作量太大。

我要测试的示例如下:

  • 如果返回类型正确(java.lang.String);
  • 如果方法的名称正确 (toString),以及它的参数 `(String thisObj, boolean isMonitoring)。

如何更好地解决这个问题?使用正则表达式?使用String.split()?

【问题讨论】:

  • 如果输出的是代码,你能测试一下生成的代码是否正确吗?
  • 理论上是的,但实际上不是。为此,我将有很多其他方法未在此处列出。
  • 您能解释一下为什么要测试这些东西吗?这个生成的代码不是在某处使用吗?如果你使用它,编译器会检查这些东西......
  • 编译器不会检查代码的语义是否正确。
  • 生成的代码将在其他地方使用,但在 waaaaaaaaaay 复杂的环境中。另外,我只会在几个月内完成整个项目,我不想等待它来测试它!

标签: java unit-testing testing


【解决方案1】:

如何编译生成代码 - 测试代码是否语法正确。

然后使用反射检查名称、参数和返回类型。

然后在 Mocked 环境中运行它以检查它是否做了它应该做的事情。

【讨论】:

  • 不知道我什么时候才能让完整的 .java 文件工作,所以编译它不是一个选项。
【解决方案2】:

我认为如果生成的代码是非常确定性的(从你的问题来看,它确实看起来是确定性的),那么我会首先从 X 中手写正确的字符串输出,然后做一个字符串比较。

例如,一个junit示例:

public void testX(){
   X gnerator = new X(getTestMethodObject());
   Assert.assertEquals(StringUtils.readFully(new File("expected_output.txt")), generator.generate());
}

显然,这将执行字符串比较,并且当生成的内容发生变化时,您必须手写新的预期输出。因此,虽然这很简单,但 以后可能会成为维护的噩梦。

当然,另一种方法是对生成的输出进行 lex 并检查生成的令牌(我假设您实际上无法在测试环境中编译生成的代码)。说,http://code.google.com/p/java-lexer/ 这是一个非常简单的 lexor(我不保证它 - 我只是在谷歌搜索几分钟后发现它......但它有 some basic tests,所以我认为它很好?)。或者,使用更多 complex like antlr 的东西,这对于测试来说可能是多余的。

我个人会坚持将手写的预期输出与生成的输出进行比较。与使用成熟的 lexors 相比,它的调性要低得多,并且更容易发现错误。

【讨论】:

  • 问题是这样我将不得不编写比我特别想测试的代码更多的代码。如果没有更好的方法,我会使用这种方法,但也许正则表达式比简单的旧字符串比较更好,imo。
  • 我认为正则表达式是对 java 代码进行 lex 的一种方法 - 毕竟,词法分析器只是一个非常复杂的状态机,与正则表达式没有什么不同。我原以为字符串比较会更容易,因为您可以连续使用 X 类生成输出的先前版本的输出作为测试,并在添加新更改时手动编辑它们。这个问题经常发生在测试 REST api 的过程中,而这个解决方案是我发现的最简单且最不麻烦的解决方案。
【解决方案3】:

你为什么不 1) 编译生成的代码并使用反射来断言“语义”,或者,如果由于依赖关系和其他东西而无法编译和加载,2) 使用 JAVA 解析器来创建抽象语法树,您可以遍历并做出断言。 (例如,ANTLR 项目有 JAVA 6 的语法)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 2019-07-19
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多