使用 Cucumber 进行回归组件测试。应该测试的层是否有任何边界?

Regression component tests with Cucumber. Is there any boundary to the layers that should be tested?

上周我发现自己不得不开始考虑如何重构仅包含单元测试的旧应用程序。我的第一个想法是使用 Cucumber 添加一些组件测试场景,以熟悉业务逻辑并确保我的更改不会破坏任何内容。但那时我与我工作的公司中的一位架构师进行了交谈,这让我想知道这是否值得,以及我必须实际测试的代码是什么。

此应用程序有许多不同类型的端点:要调用的其余端点、Oracle 存储过程以及 JMS 主题和队列。它在 war 文件中部署到 Tomcat 服务器,到代理的连接工厂和到数据库的数据源在服务器中配置并使用 JNDI 获取。

我的第一个想法是将整个应用程序加载到嵌入式 Jetty 中,指向真实的 web.xml,这样所有内容都会像从生产环境中加载一样加载,然后模拟连接工厂和数据源.通过这样做,将测试部署应用程序的基础设施的所有连接逻辑。考虑到六边形架构,考虑到这些只是逻辑应该只用于将接收到的数据转换为应用程序数据的端口,这似乎需要付出太多努力。这不应该只进行单元测试吗?

我的下一个想法是只模拟存储过程并在我的测试中加载 Spring XML,而无需任何 Web 服务器,这样可以更轻松地模拟 classes。为此,我将使用诸如 Spring MockMvc 之类的库用于其余端点,并使用 Mockrunner 用于 JMS。但是同样,这种方法仍然会测试一些适配器并使测试复杂化,因为测试的结果将是 XML 和 JSON 有效负载。在此应用程序中完成的转换非常繁重,其中相同的消息类型可能包含不同版本的 class(每条消息可能包含许多实现多个接口的复杂对象)。

所以现在我在想,也许最好的方法是只创建从入口点到应用程序的测试,从适配器调用的服务,并验证负责向代理发送消息的服务或实际调用其他 REST 端点。然后只需确保端点有适当的单元测试,并通过提供一些在真实环境中执行的冒烟测试来验证部署后一切正常。这将测试连接逻辑,而业务逻辑将被隔离测试,而不关心是添加了新适配器还是删除了适配器。

这种做法正确吗?如果不以这种方式进行测试,我会留下一些东西吗?或者还是太多了,我应该只相信单元测试?

谢谢。

您的应用程序和环境听起来很复杂。我肯定想要集成测试。我将从外向内测试应用程序,如下所示:

  • 编写一个针对实际生产环境中的应用程序运行的冒烟测试套件。黄瓜将是一个很好的工具。该套件应该只做生产中安全的事情,并且应该尽可能小,同时让您确信应用程序已正确安装和配置,并且它与其他系统的集成正在运行。

  • 编写验收测试套件,在测试环境中针对整个应用程序运行。黄瓜在这里也是不错的选择。

    我希望验收测试环境包括一个 Tomcat 服务器,其中包含生产中存在的所有服务的测试版本 Tomcat 以及一个包含架构、存储过程等的数据库。与生产相同(但不是生产数据)。通过使用 record/replay 库(例如 Betamax and/or 自己实现它们的测试版本,通过存根和模拟处理不属于您的外部依赖项。验收测试应该可以自由地对数据做任何事情,而且他们不必担心您不拥有的服务的可用性。

    编写足够的验收测试来描述应用程序的主要用例并测试应用程序各部分(子系统和 classes)之间的所有重要交互。也就是说,将您的验收测试用作集成测试。我发现验收和集成测试的目标之间几乎没有冲突。但是,不要编写超出规范和集成范围所需的验收测试,因为它们相对较慢。

  • 对每个 class 做任何有趣的事情进行单元测试,仅遗漏 class 通过您的验收测试完全测试的那些。由于您已经在进行集成测试,因此您的单元测试可以是真正的单元测试,它可以存根或模拟它们的依赖关系。 (尽管让经过单元测试的 class 使用真正的依赖关系并没有错,这些依赖关系足够简单,不会在单元测试中引起问题)。

测量代码覆盖率以确保验收和单元测试的组合测试了您的所有代码。