【问题标题】:How do I test a code generation tool?如何测试代码生成工具?
【发布时间】:2009-10-19 01:05:23
【问题描述】:

我目前正在开发我的一个小项目,该项目以动态方式生成 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

【问题讨论】:

    标签: database unit-testing testing code-generation


    【解决方案1】:

    单元测试的重点在于您知道与代码结果进行比较的答案。你必须想办法事先知道 SQL 调用。

    老实说,正如其他回答者所建议的那样,您最好的方法是提出一些预期的结果,并在单元测试中对这些结果进行硬编码。然后你可以运行你的代码,获取结果,并与硬编码的期望值进行比较。

    也许您可以记录实际生成的 SQL,而不是执行它并比较结果?

    【讨论】:

      【解决方案2】:

      这似乎是一个先有后患的情况。您不确定生成器会吐出什么,并且您有一个移动目标要测试(真正的数据库)。所以你需要把松散的末端系起来。

      创建一个小型测试数据库(例如使用 HSQLDB 或 Derby)。此数据库应使用与真实数据库相同的功能,但不要复制!您将想了解测试数据库中的每项内容的用途以及为什么存在,因此请花一些时间来提出一些合理的测试用例。针对这个(静态)测试数据库使用您的代码生成器,将结果保存为测试用例中的固定字符串。从单个功能开始。不要尝试构建完美的测试数据库作为第 1 步。你会到达那里。

      当您更改代码生成器时,运行测试。他们应该只在预期的地方休息。如果您发现错误,请在您的测试数据库中复制有问题的功能。创建一个新的测试,检查结果。它看起来正确吗?如果您可以看到错误,请修复测试中的预期输出。之后,修复生成器,使其产生正确的结果。关闭错误并继续。

      这样,您可以在沼泽中建造越来越多的安全地带。做一些你知道的事情,检查它是否有效(忽略其他一切)。如果您满意,请继续。不要试图一次解决所有问题。一步一步来。测试不会忘记,因此可以忘记正在测试的所有内容并专注于下一个功能。该测试将确保您的稳定地基不断增长,直到您可以在其上架起摩天大楼。

      【讨论】:

        【解决方案3】:

        正则表达式

        我认为SQL的语法是非常规的,但是是上下文无关的;子表达式是实现这一点的关键。您可能想为 SQL 编写一个上下文无关的解析器来检查语法错误。

        但是问问你自己:你想测试什么?你的正确性标准是什么?

        【讨论】:

          【解决方案4】:

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

          除此之外,我将测试/调试生成的代码,就像在没有单元测试的情况下测试/调试任何其他代码一样(即通过阅读、运行和/或让其他人审查它)。

          【讨论】:

          • 很遗憾,这段代码无法读取,因为从来没有写过,它是在编译时添加到boo使用的解析tee中的,因此无法读取,因此无法读取和审查:(跨度>
          • 不能在代码写入文件之类的中间添加一个步骤吗?
          • 是的,但这是否意味着我必须阅读输出以确保它有效???有点可怕,不是吗?
          【解决方案5】:

          您不必测试所有案例。收集示例调用,确保包含函数必须处理的尽可能多的困难方面,然后查看生成的代码是否正确。

          【讨论】:

            【解决方案6】:

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

            您永远无法为每个场景编写测试,但如果您编写的代码足以涵盖至少最常规的模式,您就可以相当确信您的生成器正在按预期工作。

            如果您发现它在特定场景中不起作用,请为该场景编写另一个测试并修复它。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-11-14
              • 2019-02-03
              • 2011-03-13
              • 2013-04-16
              • 1970-01-01
              • 2018-12-15
              相关资源
              最近更新 更多