【问题标题】:How to use PactJS with Cypress?如何将 PactJS 与赛普拉斯一起使用?
【发布时间】:2020-03-02 19:36:55
【问题描述】:

我想和PactJSCypress 成为朋友。

事情是这样的,因为 cypress 集成测试在浏览器内部运行,节点环境在其中不可用,因此我不能在测试中的任何地方使用 Pact 对象。

通过 Cypress 任务

尽管如此,我可以实现 cypress task,并将所有与 cypress 相关的代码移至此任务,并通过其他任务进行所有通信。这种方式流程变得过于复杂,需要在任务中支持 Pact 对象的生命周期,并复制所有消息。像这样:

cypress/plugins/index.js

const {Pact} = require("@pact-foundation/pact")
  module.exports = (on) => {
  on("task", {
    createPactServer() {
      return new Pact({
        consumer: "TodoApp",
        provider: "TodoService",
        port: 8501,
        // log: path.resolve(process.cwd(), "logs", "pact.log"),
        // dir: path.resolve(process.cwd(), "pacts"),
        logLevel: "info",
      })
    }
  })
}

cypress/integration/test.js

describe("Login page", (): void => {
  it("should log in", (): void => {
    let a = cy.task('createPactServer', );
    // do rest
    // manage verify
    // handle errors from verify
    //  shutdown pact server
    // handle all other lifecycle events.
  });
});

我想避免那种方式!

通过柏树路线

cypress 还带有route,它允许模拟网络并存根响应。我想知道是否有任何方法可以混合这些,所以我什至根本不会用 Pact 服务器监听端口。我没有找到任何方法认为我没有调查太久。还有 pact-web 在我看来只是没有 http 服务器的模拟部分,但没有关于将它与 API 集成的文档。我还发现 pact 使用 ruby​​ 文件,这可能导致无法在非节点环境中使用 w/o http 服务器。

我想知道是否无论如何尝试将它们结合在一起,以及首选的方式是什么。

【问题讨论】:

  • 这真是太及时了——我们一直在讨论如何才能使所有这些工作一起工作,但没有一个核心维护者对 Cypress 有很好的掌握。您愿意加入我们的 slack 频道以便我们在那里讨论吗?我不确定我们是否可以通过 SO 完全解决这个问题。 slack.pact.io - 你可以私信我,我们可以从那里开始。
  • 我还想了解一下我们希望我们的集成、合同和 e2e 测试一起进行的更新(哎呀,甚至使用 cypress 的 jest 插件进行单元测试)。

标签: cypress pact


【解决方案1】:

我刚刚创建了一个demonstration 应用程序,将两者结合在一起。我发现经验是quite good。它的作用:

  1. Pact 插件将为每个注册的交互动态创建一个server 和对应的route(因此它们很快)
  2. 它将设置默认路由处理程序以捕获任何未明确配置的请求(以避免错过真正的请求并因此失去信心)
  3. 仍然可以使用路由别名和cy.wait,因此可以保留开发体验,就像您没有使用 Pact 一样

我计划将其提取到单独的 cypress 插件中。

以下是使用插件的人所看到的示例测试代码:

示例

import { Matchers } from "@pact-foundation/pact-web";
const { like, eachLike } = Matchers;

let server;

const expectedProduct = {
  id: "10",
  type: "CREDIT_CARD",
  name: "28 Degrees",
};

describe("Product page", () => {
  describe("when products exist", () => {
    before(() => {
      cy.mockServer({
        consumer: "example-cypress-consumer",
        provider: "example-provider",
      }).then(opts => {
        server = opts
      })
    });

    it("can navigate to an individual product", () => {
      cy.addMockRoute({
        server,
        as: 'products',
        state: "products exist",
        uponReceiving: "a request to all products",
        withRequest: {
          method: "GET",
          path: "/products",
        },
        willRespondWith: {
          status: 200,
          headers: {
            "Content-Type": "application/json; charset=utf-8",
          },
          body: eachLike(expectedProduct),
        },
      });
      cy.addMockRoute({
        server,
        as: 'product',
        state: "a product with ID 10 exists",
        uponReceiving: "a request to get a product",
        withRequest: {
          method: "GET",
          path: "/product/10",
        },
        willRespondWith: {
          status: 200,
          headers: {
            "Content-Type": "application/json; charset=utf-8",
          },
          body: like(expectedProduct),
        },
      });

      // Navigate to products listing page
      cy.visit("http://localhost:3000");
      cy.wait("@products");

      // Filter to the product we want
      cy.get("#input-product-search").type("28 degrees");

      // Navigate to individual product
      cy.contains("See more!").click();
      cy.wait("@product");

      // ... Assert something about product page
    });
  });
});

最后的想法

我仍然认为在可能的情况下,在可以更直接针对 API 客户端的正确层进行这种形式的测试是有意义的。但这种方法可以解决许多问题(更广泛的受众、非常好的开发体验和改进用例),如果使用得当,对许多人来说可能是一条好路。

这是一个视频https://youtu.be/jTuuYMFJBBQ,它显示:

  1. 首次运行导航到 /,它调用产品列表 API /products
  2. 第二次运行扩展测试以点击进入需要点击/products/:id的产品页面。测试失败,因为尚未在 Cypress 或 Pact 中配置交互
  3. 添加product/:id 交互,瞧!

【讨论】:

    【解决方案2】:

    为什么要将柏树和契约结合起来?我以前都使用过,我认为最好避免这种依赖。

    一方面,您可以使用 cypress 进行 E2E 测试,因为 Cypress 适用于在浏览器中运行的任何东西。这意味着您不需要直接引用服务、控制器等。 另一方面,您可以使用 Pact JS(使用 mocha)进行合约测试。如您所知,Pact 遵循消费者驱动的合同方法。这意味着您必须从消费者创建 pact 文件,因为您必须对控制器(或 http 调用方法)进行单元测试,而 cypress 无法做到这一点。

    【讨论】:

    • Pact 模拟服务器不关心它是由赛普拉斯控制应用程序还是 Jest 单元测试调用。对我来说,这似乎是一个明显的组合。
    猜你喜欢
    • 1970-01-01
    • 2022-11-11
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2022-12-10
    • 1970-01-01
    相关资源
    最近更新 更多