react 快速上手开发_React中测试驱动开发的快速指南

react 快速上手开发

by Michał Baranowski

通过MichałBaranowski

React中测试驱动开发的快速指南 (A quick guide to test-driven development in React)

Following the principles of Test-Driven Development (TDD) when writing a front-end React app might seem more difficult than doing the same on the back-end.

编写前端时遵循测试驱动开发 (TDD)的原理 React应用程序似乎比在后端执行相同的操作更加困难。

First, we need to somehow render our component. Then we need to simulate user interaction with a browser. Next we respond to changes in props and state, and finally come up with a way to test asynchronous methods triggered by the click of a button.

首先,我们需要以某种方式呈现我们的组件。 然后,我们需要模拟用户与浏览器的交互。 接下来,我们响应道具状态的变化最后提出一种方法来测试单击按钮触发的异步方法。

Trying to cover all these cases in our tests often results in tests that are difficult to read. They also often depend on one another. We mock a lot, and in return we have tests full of anti-patterns.

试图在我们的测试中涵盖所有这些情况通常会导致难以阅读的测试。 他们还经常相互依赖。 我们进行了很多模拟,作为回报,我们进行了充满反模式的测试。

不要浪费你的时间 (Don’t waste your time)

From what I’ve seen, many programmers create working React components first.Then they try to cover them with tests, just to realize that the components cannot be tested in their current implementation. Then they need to refactor. Because of that they lose patience, time, and their employer’s money.

从我所看到的来看,许多程序员首先创建了可工作的React组件,然后试图通过测试覆盖它们,只是为了意识到无法在当前实现中对组件进行测试。 然后他们需要重构。 因此,他们失去了耐心,时间和雇主的金钱。

可用的解决方案 (Available solutions)

Fortunately for us, there are many testing libraries that can help us address these problems. We can try rendering React components with Enzyme and mock API responses using MockAxios. However, these libraries usually have so many methods and options that it might get confusing, especially for people who have just started writing tests.

对我们来说幸运的是,有许多测试库可以帮助我们解决这些问题。 我们可以尝试使用MockAxios渲染带有酶的 React组件和模拟API响应。 但是,这些库通常具有太多的方法和选项,可能会引起混淆,特别是对于刚开始编写测试的人。

Let’s take Enzyme for example — what’s the difference between the Shallow, Mount and Render methods? And which should you use? This is not what you should be worried about when you write your tests, in my opinion. It should be as straight forward as possible.

让我们以为例-ShallowMountRender方法之间有什么区别? 您应该使用哪个? 我认为这不是编写测试时应该担心的。 它应该尽可能直接。

我们的项目 (Our project)

For our Quick Guide purposes, we’re going to create a small React app. After clicking on a button, a random joke about Chuck Norris will be fetched and displayed.

出于快速指南的目的,我们将创建一个小型React应用。 单击按钮后,将获取并显示有关Chuck Norris的随机笑话。

No one has ever pair-programmed with Chuck Norris and lived to tell about it.
从来没有人与Chuck Norris结对编程并活着讲述这件事。

So let’s begin.

因此,让我们开始吧。

Kick-off by creating a React project in CodeSandbox, and then install the following dependencies (Jest is already pre-installed if you started from the link above):

开球创建一个阵营项目CodeSandbox 然后安装以下依赖性(j EST 如果您从上面的链接开始,则已经预先安装了):

文件夹/文件结构 (Folder/files structure)
  • src/index.js — entry point for our React app

    src / index.js —我们的React应用程序的入口点

  • src/jokeGenerator.js our container component which fetches, controls, and provides data

    src / jokeGenerator.js 我们的容器组件,用于获取,控制和提供数据

  • src/joke.js — simple presentation component

    src / joke.js —简单的演示组件

  • src/__tests__/jokeGenerator.test.js contains our tests

    src / __ tests __ / jokeGenerator.test.js 包含我们的测试

您的第一个测试 (Your first test)

Each time before we create a component we will write a failing test first and then try to make it pass. Let’s start by writing a test for our dummy component <Joke /> which will render a text from props.

每次创建组件之前,我们都会先编写一个失败的测试,然后尝试使其通过 。 让我们首先为虚拟组件<Joke />编写一个测试,该测试将通过props渲染文本。

Reading from the top: we use a render method from the react-testing-library and pass the &lt;Joke/> component (which does not exist at this point) into it. It returns an object containing a few very useful methods (find the full list of available methods here) — for example getByTestId. It then returns an HTML element based on data-testid as an argument.

从顶部开始阅读:我们使用react-testing-library中render方法,并将& lt; Jok e />组件(目前不存在)传递给它。 它返回一个包含了一些非常有用的方法的对象(可以找到我的完整列表的ThOD这儿) -为前充足getBy TestId。 然后,它返回基于data-t estidHTML元素作为参数。

Next, we write an expect using above method and data-testid, and check if the element contains the text from props. After running the tests, we get:

接下来,我们写一个想到利用上述方法和数据testid,并检查元素都包含道具的文字。 运行测试后,我们得到:

Joke is not defined
笑话未定义

Yep, we want it to fail! <Joke /> does not exist yet, remember? We have only created an empty joke.js file so far. We wrote a test in which we can clearly see what we expect the component to do. Now our job is to make the test pass without modifying the test code. Let’s do that then:

是的,我们希望它失败! <笑话 />还不存在,记得吗? 我们只创建了一个空的乔 ke.j S档为止。 我们编写了一个测试,可以清楚地看到我们期望组件执行的测试。 现在,我们的工作是使测试通过而无需修改测试代码。 然后让我们这样做:

Now, if you did everything just like I did, the test should pass :)

现在,如果您像我一样做所有事情,则测试应该通过:)

第二部分 (Second component)

Our second component will be responsible for fetching a random joke after a user clicks a button. We’ll save it in the component’s state and pass it down to our <Joke /> component. We would also like to display a default message when no joke has been loaded yet.

我们的第二个组件将负责在用户单击按钮后获取一个随机笑话。 我们将其保存为组件状态,并将其传递给我们的<Joke />组件。 当还没有玩笑时,我们还想显示一个默认消息。

Of course, we start with test first. It is a bigger component, so we’ll be writing the test step-by-step. We’ll also make sure it is passing as often as possible.

当然,我们首先要进行测试。 它是一个更大的组件,因此我们将逐步编写测试。 我们还将确保它尽可能多地通过。

We are already familiar with the render method, but this time we are taking getByText from the return object. As you might have guessed, the method returns an HTML Element if one exists in the DOM.

我们已经熟悉了render方法,但是这次我们从返回对象中获取getByText 。 您可能已经猜到了,如果DOM中存在HTML元素,该方法将返回一个HTML元素。

Run the tests and….

运行测试,然后…。

JokeGenerator is not defined
未定义JokeGenerator

You know what to do with it:

您知道如何处理它:

The test is still failing, but this time it outputs a different error:

测试仍然失败,但是这次它输出另一个错误:

Unable to find an element with the text.
找不到带有文本的元素。

You haven’t loaded any jokes yet. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

您还没有玩笑 。 这可能是因为文本被多个元素分解了。 在这种情况下,您可以为文本匹配器提供一个功能,以使匹配器更加灵活。

Let’s quickly fix that by introducing a state to our component and displaying a default message when there is no joke in the state.

让我们快速解决该问题,方法是在组件中引入一个状态并在该状态中没有笑话时显示默认消息。

Tests are passing now, so we can move on to add new functionality. Imagine that when we click on a button, the default text in the component disappears to make room for a “Loading…” message. Sounds pretty straightforward, right? We can test this scenario with only three lines of code!

测试现已通过,因此我们可以继续添加新功能。 想象一下,当我们单击一个按钮时,组件中的默认文本消失了,从而为“ 正在加载... ”消息腾出了空间。 听起来很简单,对吧? 我们可以只用三行代码测试此业务情景!

Let’s import the Simulate method first, as we’re going to need that:

首先,我们需要导入Simulate方法,因为我们需要这样做:

import { render, Simulate } from “react-testing-library”
从“ react-testing-library”导入{render,Simulate}

The difference between queryByText and getByText is in what each one returns when the element is not found. The first one returns null and the second one throws an error message. Re-running the tests:

queryByTextgetByText之间的区别在于,当找不到该元素时,每个返回的内容。 第一个返回null ,第二个返回错误消息 。 重新运行测试:

Unable to find an element with the text: Load a random joke

找不到带有文本的元素: 加载一个随机笑话

We need to create a button and set the onClick method which will set the loading state to true.

我们需要创建一个按钮并设置onClick方法,该方法会将加载状态设置为true

Just like that the test is passing again. Now it’s time to fetch our random joke! Well… it won’t be random in our tests. We’ll mock it using MockAxios.

就像测试再次通过一样。 现在是时候获取我们的随机笑话了! 好吧……在我们的测试中不会是随机的。 我们将使用MockAxios对其进行模拟

import * as axios from "axios"

从“ axios”将*作为axios导入

Above our tests in jokeGenerator.test.js, insert these two lines of code:

jokeGenerator.test.js中的测试上方,插入以下两行代码:

The first line creates a new instance of MockAxios with a random delay. The second line takes and executes a callback function after running all the tests in this file, and removes the mocked state from axios.

第一行创建一个随机延迟的MockAxios新实例。 第二行在运行此文件中的所有测试之后,采用并执行回调函数,并从axios中删除模拟状态。

At the top of our second test where we test the <JokeGenerator /> component, add:

在我们测试<JokeGenerator />组件的第二个测试的顶部,添加:

It mocks the response of any GET call done via axios. At the end of the same test:

模拟了通过axios完成的任何GET调用的响应。 在同一测试结束时:

Don’t forget to import wait:

不要忘记导入wait

import { render, Simulate, wait } from “react-testing-library”
从“ react-testing-library”导入{渲染,模拟,等待}

The wait method waits (4500ms by default) until a callback function stops throwing an error. It is checked at 50ms intervals. Basically we’re just waiting until the loading message disappears from the DOM.

wait方法等待(默认为4500ms),直到回调函数停止引发错误为止。 每隔50毫秒检查一次。 基本上,我们只是在等待加载消息从DOM中消失。

wait is also available as a separate npm package (react-testing-library uses it as a dependency). It was created by Łukasz Gozda Gandecki.

wait也可以作为单独的npm包提供 ( react-testing-library使用它作为依赖项)。 它是由ŁukaszGozda Gandecki创建的。

After making all of the code modifications and running the tests, we should get the following fail message:

在完成所有代码修改并运行测试之后,我们应该获得以下失败消息:

Expected the element not to be present

预期该元素存在

What do you think it might be? According to our test, we expect the loading message to be gone. Additionally, we want to fetch our joke from the API and save it to the state so that next expect passes.

您认为可能是什么? 根据我们的测试,我们希望加载消息消失。 另外,我们想从API中获取笑话并将其保存到状态,以便下次期望通过。

Tests should pass again now. We are sure that everything works as expected…aren’t we? Notice that we have never opened our browser and verified manually if our app even works…However, thanks to how we were writing our tests (so that our tests resemble the way the user would use the application), we can be almost 100% sure that our small app is simply working.

现在应该再次通过测试。 我们确信一切都会按预期进行,对吗? 请注意,我们从未打开过浏览器并手动验证过我们的应用程序是否可以正常工作 ……但是,由于我们编写测试的方式( 使我们的测试类似于用户使用应用程序的方式 ),我们几乎可以百分百确定我们的小型应用程序只是在工作。

As the last piece of code, let’s add this to the index.js and open the browser :)

作为最后的代码,让我们将其添加到index.js并打开浏览器:)

奖金 (Bonus)

Because of the way we wrote our tests, we can utilize them as e2e tests without adding a single line of code! All we need to do is to remove all the lines related to MockAxios and run the tests again! They will now use a real external API. Cool, isn’t it? :)

由于我们编写测试的方式,我们可以将它们用作e2e测试, 而无需添加任何代码! 我们要做的就是删除所有与MockAxios相关的行, 然后再次运行测试! 他们现在将使用真正的外部API。 不错,不是吗? :)

摘要 (Summary)

All the code is available on the project’s CodeSandbox. I really encourage you to get familiar with a full react-testing-library documentation. You’ll find there many more examples and use cases.

所有代码都可以在项目的CodeSandbox上找到 我真的鼓励您熟悉完整的react-testing-library文档。 您会发现更多示例和用例。

I hope you enjoyed my Quick Guide to TDD in React, and that you’ve learned something new today.

希望您喜欢React中的TDD快速指南,并且今天学到了新知识。

翻译自: https://www.freecodecamp.org/news/quick-guide-to-tdd-in-react-81888be67c64/

react 快速上手开发

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
This book will teach the concepts of test driven development in Java so you can build clean, maintainable and robust code About This Book Explore the most popular TDD tools and frameworks and become more proficient in building applications Create applications with better code design, fewer bugs, and higher test coverage, enabling you to get them to market quickly Implement test-driven programming methods into your development workflows Who This Book Is For If you're an experienced Java developer and want to implement more effective methods of programming systems and applications, then this book is for you. What You Will Learn Explore the tools and frameworks required for effective TDD development Perform the Red-Green-Refactor process efficiently, the pillar around which all other TDD procedures are based Master effective unit testing in isolation from the rest of your code Design simple and easily maintainable code by implementing different techniques Use mocking frameworks and techniques to easily write and quickly execute tests Develop an application to implement behavior-driven development in conjunction with unit testing Enable and disable features using feature toggles In Detail Test-driven development (TDD) is a development approach that relies on a test-first procedure that emphasizes writing a test before writing the necessary code, and then refactoring the code to optimize it.The value of performing TDD with Java, one of the longest established programming languages, is to improve the productivity of programmers and the maintainability and performance of code, and develop a deeper understanding of the language and how to employ it effectively. Starting with the basics of TDD and understanding why its adoption is beneficial, this book will take you from the first steps of TDD with Java until you are confident enough to embrace the practice in your day-to-day routine.You'll be guided through setting up tools, frameworks, and the environment you need,

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值