赛普拉斯 12864_赛普拉斯端到端测试中的模拟HTTP调用

赛普拉斯 12864

介绍 (Introduction)

If your web development team is anything like mine, you’ll understand the value and importance of tests to support and continue to verify your application’s functionality (even if you’re not a huge fan of writing tests, which sometimes, I’m not).

如果您的Web开发团队像我一样,您将了解测试的价值和重要性,以支持并继续验证您的应用程序的功能(即使您不是编写测试的忠实拥护者,有时我也不是。 )。

Unit tests, integration tests, and end-to-end tests in particular are a way to safeguard against bugs popping up in seemingly unrelated pieces of code while you’re building out cool, new features.

单元测试,集成测试,尤其是端到端测试,是一种在构建炫酷的新功能时,防止在看似无关的代码段中弹出错误的方法。

End-to-end testing, in case you’re less familiar with it, is a technique for testing the entire software product from beginning to end to ensure the application flow behaves as expected. Basically, an automated test is written to control a browser as a user would; it types text into inputs, clicks buttons, looks for page elements, etc. just as if a user was controlling the application, to ensure the system behaves as intended.

端到端测试(如果您不太熟悉的话)是一种从头到尾测试整个软件产品,以确保应用程序流按预期运行的技术。 基本上,编写了一个自动化测试来像用户一样控制浏览器。 它将文本键入输入,单击按钮,查找页面元素等,就像用户在控制应用程序一样,以确保系统按预期运行。

But if your web application is anything like the one we build and support, it depends on external data sources from other teams, both within and outside of our organization, which means we can’t always rely on that data (especially when it comes to non-production data) to be clean, accurate, or — in some cases, even in existence. This is why, when it comes to writing and running our end-to-end (e2e) tests (which are the tests that depend on external data), we mock (or “stub”) those API calls instead of hoping the stars align and no one else has changed that same data to suit their needs.

但是,如果您的Web应用程序类似于我们构建和支持的Web应用程序,则它依赖于组织内部和外部其他团队的外部数据源,这意味着我们不能总是依赖于该数据(尤其是涉及到非生产数据),以确保数据干净,准确,或者在某些情况下甚至存在。 这就是为什么在编写和运行端到端(e2e)测试(取决于外部数据的测试)时,我们模拟(或“存根”)那些API调用,而不希望星号对齐而且没有人更改过相同的数据以适合他们的需求。

Unreliable lower life cycle data, outside of the control of your development team, is no reason to keep new code from being merged in and deployed to production. But the old adage “It works on my machine” 🤷‍♀ is also not a valid justification because who knows that the same will hold true when deployed somewhere besides a local development laptop.

在开发团队无法控制的范围内,不可靠的较低生命周期数据是没有理由避免将新代码合并到生产环境中。 但是,古老的格言“它可以在我的机器上工作”也不是合理的理由,因为谁知道,将其部署在本地开发笔记本电脑之外的其他地方也一样。

So let’s discuss how to cut out the (potentially) bad data and stub good data (the kind of data scenarios we’d expect to encounter in real life) when using Cypress for end-to-end testing.

因此,让我们讨论使用赛普拉斯进行端到端测试时,如何切掉(潜在的)不良数据和存根好数据(我们希望在现实生活中遇到的那种数据场景)。

Tip: Use Bit (Github) to share, document, and manage reusable React components from different projects. It’s a great way to increase code reuse, speed up development, and build apps that scale.

提示 :使用Bit ( Github )共享,记录和管理来自不同项目的可重用React组件。 这是增加代码重用,加速开发并构建可扩展应用程序的好方法。

认识关键玩家进行e2e测试 (Meet the Key Player for e2e Tests)

For our React application, we use the popular e2e framework Cypress to run our own end-to-end tests, and one awesome feature of Cypress is that it’s actually JavaScript framework agnostic and can be utilized even if you’re writing an app in vanilla JS.

对于我们的React应用程序,我们使用流行的e2e框架赛普拉斯来运行我们自己的端到端测试,赛普拉斯的一个令人敬畏的功能是它实际上与JavaScript框架无关,即使您使用香草编写应用程序也可以使用它。 JS。

This is great news, because it means this tutorial can apply to you and your app, even if you’re using Angular, Vue, Svelte or some other cutting edge JS framework I’ve not even heard of yet. 😄

这是个好消息,因为这意味着即使您使用的是Angular,Vue,Svelte或其他我尚未听说的尖端JS框架,本教程也可以适用于您和您的应用程序。 😄

那为什么是柏树呢? (So Why Cypress?)

When we started building our current application we actually began building our e2e tests with Puppeteer, and it was never much fun. The syntax was unintuitive, the tests were flaky, debugging was hard and it just wasn’t a great developer experience overall.

当我们开始构建当前的应用程序时,我们实际上开始使用Puppeteer构建我们的e2e测试,这从来没有那么有趣。 语法不直观,测试不可靠,调试困难,并且总体上并不是很好的开发人员经验。

I’d heard Cypress talked about by many developers I really respected, and without too much convincing on my part, my team gave it a try and we’ve been using it ever since. Cypress just makes end-to-end tests easy in a way I’ve never experienced before (I’ve also worked with Selenium in the past, and that too had a bit of a steep learning curve), set up was a breeze, debugging is much nicer with a great headed browser feature, and the documentation on its website is pretty good, to boot. And Cypress can work with any browser-based JavaScript application — as I mentioned above.

我听过赛普拉斯(Cypress)受到许多我真正尊敬的开发人员的谈论,并且在我没有太多说服力的情况下,我的团队尝试了一下,从那时起我们一直在使用它。 赛普拉斯以前所未有的方式(过去我也曾与Selenium一起工作,而且学习曲线也有些陡峭)使端到端测试变得容易,设置起来很轻松,强大的浏览器功能可以使调试工作变得更加轻松,而且引导时其网站上的文档也很好。 赛普拉斯可以与任何基于浏览器JavaScript应用程序一起使用-如上所述。

So if you’re considering different e2e testing frameworks and Cypress is an option, I would recommend you give it a try. I doubt you’ll regret it.

因此,如果您考虑使用不同的e2e测试框架,并且可以选择Cypress,那么我建议您尝试一下。 我怀疑你会后悔。

So now that I’ve sold you on why we chose Cypress for our e2e testing, it’s time to describe how to mock data requests so malformed (or missing) data outside of your control doesn’t bring your development to a screeching halt.

因此,既然我已经向您出售了为什么我们选择赛普拉斯进行e2e测试,现在该描述如何模拟数据请求,以便控制范围之外的畸形(或丢失)数据不会使您的开发陷入停顿。

设置模拟数据以使赛普拉斯在查询后返回 (Setting up Mocked Data for Cypress to Return when Queried)

I’m going to be demoing how to do this test mocking with a shopping cart: displaying an empty cart, displaying a list items to purchase, and displaying a list of cart items already purchased. Bear in mind the examples are simplified for ease of understanding, but the parts important to successfully mocking these HTTP calls with different data is there.

我将演示如何用购物车进行此测试模拟:显示一个空的购物车,显示要购买的商品列表以及显示已经购买的购物车商品列表。 请记住,示例是为了易于理解而简化的,但是这里有对于成功模拟具有不同数据的HTTP调用很重要的部分。

The first step in this tutorial revolves around stubbing the right data that should be returned when Cypress queries a REST endpoint.

本教程的第一步围绕存根正确的数据,这些数据在赛普拉斯查询REST端点时返回。

That’s easy enough to do. In our project there’s a cypress folder at the root level of the project that holds: all the Cypress tests (in the /integrations folder), the mocked routes (in the /mocks folder), and the folder of test JSON data (in the /fixtures folder).

这很容易做到。 在我们的项目中,项目根目录下有一个cypress文件夹,其中包含:所有Cypress测试(在/integrations文件夹中),模拟路由(在/mocks文件夹中)和测试JSON数据文件夹(在/fixtures文件夹)。

We’ll begin in the /fixtures folder. It’s here that I’ll create a JSON file of all the test data I need, and name it cart_mock_data.json.

我们将从/fixtures文件夹开始。 我将在这里创建一个我需要的所有测试数据的JSON文件,并将其命名为cart_mock_data.json

cart_mock_data.json

cart_mock_data.json

Image for post
This JSON file contains the stubbed cart data to be returned by the mocked HTTP call.
此JSON文件包含要通过模拟HTTP调用返回的存根购物车数据。

This file contains three different data sets, which will be returned by the same mocked HTTP route according to which root data object is called: getCurrentCartItems, getEmptyCart or getPreviouslyOrderedItems.

该文件包含三个不同的数据集,它们将由相同的模拟HTTP路由根据调用的根数据对象返回: getCurrentCartItemsgetEmptyCartgetPreviouslyOrderedItems

Don’t worry if that sentence seems a little unclear, it will make more sense when you see it implemented in practice.

如果该句子看起来有些不清楚,请不要担心,当您在实践中看到它时,它会更有意义。

As you can probably guess, the current cart items are items still to be bought, the empty cart data is what a cart call with no cart items looks like, and the previously ordered items are items bought and in various states of being packed, shipped and delivered to the customer.

您可能会猜到,当前的购物车商品是仍有待购买的商品,空的购物车数据是没有购物车商品的购物车呼叫的样子,而先前订购的商品是已购买的商品,处于打包,运输的各种状态并交付给客户。

Now that the data is stubbed out, let’s move on to mocking the HTTP call that will deliver this data during the tests.

现在数据已经存根了,让我们继续模拟将在测试期间提供此数据的HTTP调用。

编写模拟的HTTP调用 (Writing the Mocked HTTP Calls)

Cypress makes setting up managed network requests very easy with cy.route(). This method is flexible and can take in a variety of parameters, and the way we use it is with the syntax of: cy.route(method, url, response).

赛普拉斯可使用cy.route()轻松设置托管网络请求。 该方法很灵活,可以接受各种参数,我们使用它的方式是cy.route(method, url, response)语法

These route mocking files go in the /mocks folder (seems logical, right?), and this one, since it’s related to the shopping cart is named: cartMocks.js.

这些路线模拟文件位于/mocks文件夹中(似乎合乎逻辑,对吗?),因为它与购物车有关,所以将其命名为: cartMocks.js

cartMocks.js

cartMocks.js

Image for post
The code to mock the HTTP call for the Cypress end-to-end cart test.
模拟Cypress端到端购物车测试的HTTP调用的代码。

To make the route mocks more flexible and reusable, we made each real HTTP call in our application into a separate arrow function mocking that same call.

为了使路由模拟更加灵活和可重用,我们在应用程序中将每个真实的HTTP调用转换为模拟该调用的单独的箭头函数。

And as you can see from the code snippet above for the function getCartItems(), it defines an endpoint (and is slightly more reusable because the endpoint can be modified to fetch already purchased cart items too, if the type parameter is "purchased"), and then sets up the mocked route. The method is a "GET", the url consists of the endpoint variable plus the user’s userInfo.userName to ensure the right cart items for the user are fetched, and the response is whatever we want it to be (which is defined in the cart_mock_data.json file).

正如您从上面的函数getCartItems()的代码片段中所看到的,它定义了一个endpoint (并且可重用性更高,因为如果type参数为"purchased" ,也可以将端点修改为获取已经购买的购物车商品) ,然后设置模拟路线。 该method"GET"urlendpoint变量加上用户的userInfo.userName以确保为用户提取了正确的购物车商品,并且response是我们想要的(在cart_mock_data.json定义) cart_mock_data.json文件)。

The as('getCartItems'); code at the end of the cy.route() call is an alias in Cypress. When using an alias with routes in Cypress, it’s an easy way to ensure your application makes the intended requests and waits for your server to send the response. You’ll see an example of route aliases in action in the actual tests below.

as('getCartItems'); cy.route()调用末尾的代码是赛普拉斯的别名 。 在赛普拉斯中使用带路由的别名时,这是一种确保应用程序发出预期请求并等待服务器发送响应的简便方法。 您将在下面的实际测试中看到实际使用的路由别名的示例。

用赛普拉斯测试中的模拟调用替换实际的HTTP调用 (Replacing Actual HTTP Calls with the Mocked Calls in Cypress Tests)

And the last step in the tutorial: how to set these HTTP calls up so they return the stubbed data instead of attempting to hit your actual databases or backend services.

本教程的最后一步:如何设置这些HTTP调用,以便它们返回存根数据,而不是尝试访问实际的数据库或后端服务。

The actual test files go in the /integrations folder, and since this one pertains to the cart, it’s named cartSpec.js. Below, I’ll show you three separate tests (which can all be in the same test file, just different describe() test blocks), using the same mocked route and returning different data each time.

实际的测试文件位于/integrations文件夹中,并且由于该文件与购物车相关,因此将其命名为cartSpec.js 。 在下面,我将向您展示三个单独的测试(它们都可以在同一个测试文件中,只是不同的describe()测试块),它们使用相同的模拟路由并每次返回不同的数据。

First up is the test where the cart should show as empty.

首先是测试,购物车应显示为空。

cartSpec.js

cartSpec.js

Image for post
This test checks that the cart has an empty icon when there’s no cart items returned from the mocked endpoint.
当没有从模拟端点返回购物车项目时,此测试检查购物车是否具有空图标。

Let’s step through each piece of this test.

让我们逐步完成此测试的每一部分。

Before you can begin routing requests, you must start the server, hence the cy.server() you’ll see in each test’s beforeEach() function that sets up the environment for the test.

在您开始路由请求,必须启动服务器,因此cy.server()你会在每一个测试来看看beforeEach()函数,设置了用于测试的环境。

Next, the cy.fixture() function is how to actually load a fixed set of data located in a file (the cart_mock_data.json file, for us) by providing the file path as the function param, and then returning the promise it creates to access that fixture’s data and pass it to our mocked route.

接下来, cy.fixture() 函数是如何通过提供文件路径作为函数参数来实际加载文件(对我们来说是cart_mock_data.json文件)中的一组固定数据,然后返回其创建的承诺来访问灯具的数据并将其传递到我们嘲笑的路线。

The rc is the data inside of the file, and by passing rc.getEmptyCart to the cartMocks.getCartItems() mocked route (which is imported at the very top of the file) plus a userName object and "pending" cart item type, when that data in the JSON file is accessed, the object with the key of getEmptyCart will be returned.

rc是文件中的数据,通过将rc.getEmptyCart传递到cartMocks.getCartItems()路线(在文件的最顶部导入),再加上userName对象和"pending"购物车商品类型,当如果访问了JSON文件中的数据,则将返回键为getEmptyCart的对象。

Then the cy.visit() navigates the browser to the cart page by passing the in the /cartPage URL.

然后, cy.visit()通过在/cartPage URL中传递将浏览器导航到购物车页面。

And finally, the route alias I referenced earlier above comes into play with cy.wait('@getCartItems'). The cy.wait() actually waits for a specified number of milliseconds OR for an aliased resource to resolve before moving on to the next command. So when this beforeEach() function runs, it requests the mocked data and ensures it’s returned before moving on to the actual test.

最后,我在上面引用的路由别名与cy.wait('@getCartItems')cy.wait() 在继续下一个命令之前,实际上要等待指定的毫秒数或别名资源解析。 因此,当此beforeEach()函数运行时,它会请求beforeEach()的数据并确保在继续进行实际测试之前将其返回。

In this case, it’s easy because the returned data is an empty array [], and the test just verifies the text "Your Cart is empty." is present on the screen. Not too tough, right?

在这种情况下,这很容易,因为返回的数据为空数组[] ,而测试仅验证文本"Your Cart is empty." 出现在屏幕上。 不太强硬吧?

Here’s another test (in the same test file), but this one tests whether cart items that have yet to be purchased appear in the cart when data is supplied to the getCartItems mock.

这是另一项测试(在同一测试文件中),但是此测试用于在将数据提供给getCartItems模拟时,是否尚未购买的购物车商品出现在购物车中。

cartSpec.js

cartSpec.js

Image for post
This test checks that the cart displays cart items not yet purchased when pending cart items are requested from the mocked endpoint.
此测试检查从模拟端点请求挂起的购物车项目时,购物车是否显示尚未购买的购物车项目。

This test should be more self explanatory after the thorough run down I gave in the first test.

我在第一个测试中彻底失败后,该测试应该更能说明问题。

Once again, set up the mock server and fixture to return data from the JSON file. You will notice, however, for this test, the getCurrentCartItems object is returned this time when the userName and "pending" cart item type are supplied to the HTTP mock call. This data is a list of cart items that resemble actual cart item data that comes back from our actual cart service, minus having to depend on having a real user’s cart at hand with cart items present.

再次设置模拟服务器和夹具,以从JSON文件返回数据。 但是,您会注意到,对于此测试,当将userName"pending"购物车项目类型提供给HTTP模拟调用时,这次会返回getCurrentCartItems对象。 此数据是类似于从我们的实际购物车服务返回的实际购物车数据的购物车列表,而不必依赖于手边有真实用户的购物车以及当前的购物车项目。

And in the actual test, inside the it() statement, the end-to-end test checks to make sure the “test product” cart item names are displayed in the correct order, with most recently added items on top.

在实际测试中,在it()语句中,端到端测试检查以确保“test product”购物车商品名称以正确的顺序显示,最新添加的商品位于顶部。

Seems pretty easy again, right? Let’s look at one more test, this one will test that only purchased items are displayed when the "purchased" cart item type parameter is passed into the mocked HTTP call.

似乎再简单不过了吧? 让我们再看一个测试,该测试将测试在将"purchased"购物车商品类型参数传递到模拟的HTTP调用中时,仅显示购买的商品。

cartSpec.js

cartSpec.js

Image for post
This last test checks that the cart displays already purchased cart items when purchased cart items are requested from the mocked endpoint.
当从模拟的端点请求购买的购物车物品时,此最后的测试检查购物车是否显示已购买的购物车物品。

For this test, the same steps happen again: start the mocked server, call the fixture and pass it JSON data, specify the getPreviouslyOrderedCartItems response object as well as a userName and "purchased" cart item type for this call (since that endpoint is modified slightly from the original getCartItems URL), and visit the cart item page, waiting for the mocked HTTP call to return data.

对于此测试,将再次执行相同的步骤:启动模拟服务器,调用灯具并将其传递给JSON数据,指定getPreviouslyOrderedCartItems响应对象以及此调用的userName"purchased"购物车商品类型(因为已修改端点)稍微偏离原始getCartItems URL),然后访问购物车商品页面,等待getCartItems的HTTP调用返回数据。

Then the test checks that just already purchased cart items are present, and we’re done.

然后测试检查是否存在刚刚购买的购物车物品,并且我们已经完成。

Of course, Cypress e2e tests can (and do) get a lot more complicated than the examples I’ve shown above, but hopefully this will help get you going in the right direction with your own e2es, especially when mocked data from another server or service is needed.

当然,赛普拉斯e2e测试可以(并且确实)比我上面显示的示例复杂得多,但是希望这可以帮助您正确使用自己的e2e,特别是在从另一台服务器或其他服务器上模拟数据时需要服务。

结论 (Conclusion)

Testing, although it may not be fun to write, helps ensure that all parts of a web application continue to function as they should, even as new features are added. End-to-end tests, one of the myriad of testing types available tests an application’s flow as an actual user would: toggling buttons, clicking drop downs, checking items are visible or not on a page, etc.

尽管编写起来可能并不有趣,但是测试有助于确保Web应用程序的所有部分都可以继续正常运行,即使添加了新功能也是如此。 端到端测试是可用的众多测试类型之一,它可以像实际用户一样测试应用程序的流程:切换按钮,单击下拉列表,检查项目是否在页面上可见等。

But although tests (and good test coverage) are a critical part of my development team’s process, the data we depend on from other teams, outside of our control, is not always the most reliable. For this reason, we choose to mock our Cypress HTTP calls to those outside services in our e2es to ensure that bad test data isn’t the thing holding us back from adding new functionality our users want. And trust me, it’s saved us a ton of extra time and headaches trying to debug why things aren’t working right.

但是,尽管测试(和良好的测试覆盖率)是我开发团队流程的关键部分,但我们依赖于其他团队(在我们控制范围之外)所依赖的数据并不总是最可靠的。 因此,我们选择在e2es中模拟对外部服务的Cypress HTTP调用,以确保不良的测试数据不会阻止我们添加用户想要的新功能。 相信我,它为我们节省了大量的时间和精力,以调试出现问题的原因。

Check back in a few weeks — I’ll be writing more about JavaScript, React, ES6, or something else related to web development.

几周后再回来查看-我将写更多有关JavaScript,React,ES6或其他与Web开发相关的内容。

Thanks for reading. I hope this helps you write end-to-end tests with more ease, giving yourself and your team more confidence that all parts of your system work as expected, despite adding new code and features, or having unreliable test data in lower life cycles. 🙂

谢谢阅读。 我希望这可以帮助您更轻松地编写端到端测试,尽管增加了新的代码和功能,或者在较低的生命周期中拥有不可靠的测试数据,但使您自己和团队更加自信系统的所有部分都能按预期工作。 🙂

使用Bit共享和管理可重复使用的React组件 (Share & Manage Reusable React Components with Bit)

Use Bit (Github) to share, document, and manage reusable components from different projects. It’s a great way to increase code reuse, speed up development, and build apps that scale.

使用Bit ( Github )共享,记录和管理来自不同项目的可重用组件。 这是增加代码重用,加速开发并构建可扩展应用程序的好方法。

Image for post
React components shared on Bit.dev
React在 Bit.dev上共享的组件

相关故事 (Related Stories)

参考资料和其他资源 (References and Further Resources)

翻译自: https://blog.bitsrc.io/mocking-http-calls-in-cypress-end-to-end-tests-fa2e6b7caaf7

赛普拉斯 12864

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值