【问题标题】:How to manage application data for functional tests?如何管理功能测试的应用程序数据?
【发布时间】:2014-07-22 07:38:23
【问题描述】:

我们目前正在通过引入功能测试来提高我们正在运行的一组数据库支持的应用程序(或“服务”)的测试覆盖率。对我来说,功能测试将被测系统 (SUT) 视为一个黑盒,并通过其公共接口对其进行测试(无论是 Web 接口、REST 还是我们使用 AMQP 进入消息传递领域的潜在冒险) )。

为此,测试用例A) 引导应用程序的实例B) 使用已在运行的实例

A 版本允许测试用例通过构建工具的测试阶段或 CI 作业内部轻松测试系统的当前版本。这就是例如Grails functional test phase 是为了。或Maven could be set up 这样做。

B 版本要求系统已经运行,但系统可能位于(或至少更接近)生产环境中。 Grails 可以在执行功能测试时通过-baseUrl 选项做到这一点。

现在让我感到困惑的是如何在每个测试用例执行之前实现服务的所需状态?

如果我例如想要测试一个执行基本 CRUD 的 REST 接口,如何在数据库中创建一个实体以便测试它的 HTTP GET?

我看到了不同的可能性:

  1. 使用相同的 API(例如 HTTP POST)来创建实体。缺点:更改创建方法会破坏两个测试用例。此外,可能没有适用于所有 API 的创建方法。
  2. 添加附加 CRUD API 用于测试,并且仅在非生产环境中激活它。然后将该 API 用于测试。缺点:向生产系统添加额外的代码,API 逻辑可能不是微不足道的,例如创建复杂的实体图(通过聚合/组合),我们需要确保 API 未激活用于生产。
  3. Grails 远程控制插件基本上遵循相同的方法。它允许您“进入您的应用程序”并通过序列化调用任意代码。缺点:感觉“脆弱”。不同的语言/框架可能有类似的机制(这个问题不是 Grails 特有的)。
  4. 直接访问关系数据库和创建/删除内容,例如使用 DbUnit 或仅通过 JDBC 手动创建实体。缺点:您在测试用例中重复创建/删除逻辑和/或 ORM。尽管 SUT 仍然有效,但重构 DB 会破坏测试用例。

除了这些可能性之外,Grails 在使用 (-inline) 选项进行功能测试时允许访问 Spring 服务(因为应用程序实例在与测试用例相同的 JVM 中运行)。同样适用于Spring Boot "integration tests"。但我无法针对已经运行的应用程序版本运行测试(如上面的选项 B 所述)。

那么你是怎么做到的呢?我错过了任何选择吗?

另外,您如何保证每个测试用例在自己之后正确清理,以便下一个测试用例看到 SUT 处于相同状态?

【问题讨论】:

    标签: java spring grails testing functional-testing


    【解决方案1】:
    • 与单元测试一样,您希望在运行功能测试之前拥有一个“干净”的数据库。您将需要一些设置/拆卸功能来使数据库进入定义状态。

    • 清理数据库最简单/最快的解决方案是使用 sql 脚本删除所有内容。 (对于调试,在测试setup 中运行它也很有用,以在测试失败后保持数据库的状态。)这可以手动维护(它只包含delete <table> 语句)。如果您的数据库经常更改,您可以尝试生成干净的脚本(禁用外键(以避免排序问题),删除表)。

    • 要生成测试数据,您也可以使用 sql 脚本,但这很难维护,或者通过代码创建。代码可以放在普通的Services中。如果您不需要真正的生产数据,build-test-data 插件对于简化测试数据的创建非常有帮助。如果您在代码方面,那么重用生产代码来创建测试数据以避免重复也是有意义的。

    • 调用测试数据设置只需使用遥控器。我不认为它比所有 http 和 ajax 的东西更脆弱 ;-)。由于我们现在在服务中拥有所有创建代码,因此您唯一需要使用远程控制调用的是创建数据的服务。它不必比remote { ctx.testDataService.setupDataForXyz() } 更复杂。如果就这么简单,您甚至可以放下遥控器并使用控制器/动作来运行它。

    • 不要在功能测试中测试太多细节,以免它变得更复杂。 :)

    【讨论】:

    • 恕我直言,您的第 2 点很老套。并且数据库中的干净(=无数据)状态可能不是我们想要的,因为应用程序需要一些数据才能运行(例如安全角色,...)。如果您在测试设置中创建此数据,这将使我们达到上面的第 4 点。第 4 点:哪些 AJAX 东西?你是对的,RemoteControl 可能比创建 CRUD 服务的工作量少。我喜欢拥有testDataService inside 生产代码的想法。
    • 关于数据库清理:当然你可以只清理被触及的数据。如果您只读了主数据,则可以保留它。一个清晰的方法比为每个测试维护不同的清理逻辑要容易/快得多。我还从服务中运行它,因此它很容易集成到设置中。 Ajax 的东西只是对易碎性和远程控制方向的一般评论。与您的问题没有具体关系:)
    猜你喜欢
    • 2014-07-05
    • 1970-01-01
    • 2017-10-05
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    相关资源
    最近更新 更多