如何测试代码生成工具?

10
我目前正在开发一个小项目,以动态方式生成SQL调用,供其他软件使用。由于SQL调用事先不知道,因此我希望能够对生成SQL的对象进行单元测试。您有什么最佳实践建议吗?请注意,无法知道所有可能生成的SQL调用。
目前我唯一想到的方法是使用正则表达式创建接受SQL的测试用例,并确保SQL可以编译,但这并不能确保调用返回预期结果。
编辑:添加更多信息:
我的项目是Boo的扩展,允许开发人员使用一组属性来标记其属性。这些属性用于确定开发人员希望如何在数据库中存储对象。例如:
# This attribute tells the Boo compiler extension that you want to
# store the object in a MySQL db. The boo compiler extension will make sure that you meet
# the requirements
[Storable(MySQL)] 
class MyObject():
    # Tells  the compiler that name is the PK
    [PrimaryKey(Size = 25)]
    [Property(Name)]
    private name as String

    [TableColumn(Size = 25)]
    [Property(Surname)]
    private surname as String

    [TableColumn()]
    [Property(Age)]
    private age as int

伟大的想法是生成的代码不需要使用反射机制,而是在编译时添加到类中。编译时间会更长,但根本不需要使用反射。目前,我已经让代码在编译时生成了所需的方法来返回SQL语句,它们被添加到对象中并可以被调用,但我需要测试生成的SQL是否正确 :P

6个回答

3
整个单元测试的关键在于你知道要比较代码结果的答案。你必须找到一种方法来提前了解SQL调用。
老实说,就像其他回答者建议的那样,你最好制定一些预期结果,并在单元测试中硬编码这些结果。然后,你可以运行代码,获取结果,并与硬编码的预期值进行比较。
也许你可以记录实际生成的SQL,而不是执行它并比较结果?

2
这似乎是一个鸡生蛋的问题,你不确定生成器会输出什么,也有一个动态目标需要进行测试(真实数据库)。因此,你需要把松散的线条捆绑起来。
创建一个小的测试数据库(例如使用HSQLDB或Derby)。该数据库应该使用与真实数据库相同的功能,但不要复制!您需要了解测试数据库中的每个内容以及其存在的原因,因此请投入一些时间来构思一些合理的测试案例。针对这个(静态)测试数据库使用你的代码生成器,将结果保存为固定字符串在你的测试案例中。从单一的特性开始,不要试图在第一步建立完美的测试数据库,你会成功的。
当你更改代码生成器时,请运行测试用例。它们应该只会在预期的位置中出现错误。如果你发现了一个bug,请在你的测试数据库中复制涉及到问题的那个特性。创建一个新的测试,检查结果。它看起来正确吗?如果你能看到错误,请在测试中修正期望的输出。之后,修复生成器以便它可以创建正确的结果。关闭bug并继续前进。
这样,你就可以在沼泽地上建立更多更加安全的基础。做自己知道的东西,检查它是否有效(忽略其他一切)。如果你满意,继续前进。不要试图一次解决所有问题。一步一步来。测试用例不会忘记,因此您可以忘记正在测试的所有内容,并集中精力处理下一个特性。测试将确保你的稳定基础不断增长,直到你能在其上搭建摩天大楼。

1
正则表达式
我认为 SQL 的语法是非正则的,但是上下文无关;子表达式是实现这一点的关键。您可能需要编写一个上下文无关解析器来检查 SQL 的语法错误。
但是请问自己:你想要测试什么?你的正确性标准是什么?

1

如果你正在生成代码,为什么不同时生成测试呢?

如果无法实现上述操作,我会像测试/调试其他没有单元测试的代码一样来测试/调试生成的代码(即通过阅读、运行或让他人审核等方式)。


不幸的是,这段代码无法被读取,因为它从未被编写,它是在 Boo 编译时添加到解析树中的。因此,无法读取和审查它 :( - mandel
不可能添加一个中间步骤,将代码写入文件或其他东西吗? - Anders Sandvig
是的,但这是否意味着我必须阅读输出以确保它有效?有点可怕,不是吗? - mandel

0

您不必测试所有情况。制作一个示例调用集合,确保包括尽可能多的函数需要处理的困难方面,然后查看生成的代码是否正确。


0

我会编写一套测试,输入已知的数据并检查生成的SQL是否符合预期。

虽然不可能为每种情况编写测试,但如果编写足够多的测试以覆盖至少最常见的模式,您可以相当自信地确保生成器按预期工作。

如果发现在特定情况下无法正常工作,请为该情况编写另一个测试并进行修复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接