如何使用Redux-saga和ReactDnD测试React和Redux(哇!)

楚勇
2023-12-01

by Gregory Beaver

通过格雷戈里·海狸

如何使用Redux-saga和ReactDnD测试React和Redux(哇!) (How to test React and Redux with Redux-saga and ReactDnD (whew!))

帮助程序和系统使测试更加容易 (Helpers and systems to make testing easier)

This article is the one I wish I had found before I started coding using all the fanciness of React.

我希望在开始使用React的所有奇妙功能进行编码之前找到这篇文章。

I’m currently working on a complex offline-first eventually-consistent scheduling application for a summer music program to replace a Mac app written in Objective C many years ago.

我目前正在为夏季音乐程序开发一个复杂的,离线的,最终一致的日程安排应用程序,以替换多年前用Objective C编写的Mac应用程序。

The application uses:

该应用程序使用:

  • a Node.js backend in Express, with data stored in CouchDB with PouchDB in the browser to persist state between sessions and to manage replication and conflicts, and React with Redux on the frontend, Redux-saga to manage asynchronous events, and to spice it up, a dash of drag and drop fun with React-DnD. It’s also a test-driven application, with 100% test coverage and currently a ratio of 591 lines of source code to 7040 lines of test code.

    使Node.js的后端快递 ,与存储在数据的CouchDBPouchDB在浏览器会话之间保持状态和管理复制和冲突,并作出React终极版的前端, 终极版-佐贺管理异步事件和香料它向上, React-DnD带来了一些拖放乐趣。 它也是一个测试驱动的应用程序,具有100%的测试覆盖率,目前源代码行数为591行,测试代码行数为7040。

The lessons I’ve learned about avoiding brittle tests, overly dependent tests and making it easy to test just one thing in one test are encapsulated in this article.

本文总结了我所学到的避免易碎测试,过分依赖测试以及简化一项测试中的一件事的经验。

First things first: this article assumes you will be transpiling es6 using babel, or using it directly in bleeding edge browsers. If you need to learn about this, there are many, many great resources on how to set up babel with webpack or other bundlers to serve your app. This article only focuses on how to test things once your environment is up and running.

首先,第一件事:本文假设您将使用babel来转译es6,或者直接在最新的浏览器中使用它。 如果您需要了解这一点,那么有很多关于如何使用webpack或其他捆绑器设置babel来为您的应用服务的大量资源。 本文关注环境启动并运行后如何进行测试。

TL; DR (TL;DR)

Check the source at https://github.com/cellog/testHelper

https://github.com/cellog/testHelper中检查源

But you’re going to want to read this!

但是您将要阅读此书!

为什么这些东西甚至很重要? (Why does this stuff even matter?)

Story time! I began coding many years ago, and have seen many trends come and go. The Object-oriented craze of the 80s and 90s revolutionized code separation, but led to unmaintainable code. When I studied computer science (briefly) in the early 90s, it was a bit like the wild west. They gave us problems, and we hacked until it worked. Mostly. There was no way to verify the system except by running your program and comparing the output to expected output as one monolithic clusterf… clusterfantasy. Clusterfriend. You get the idea.

讲故事的时间! 我从多年前开始编写代码,并且已经看到了许多趋势。 80年代和90年代的面向对象的狂潮彻底改变了代码分离,但导致了无法维护的代码。 当我90年代初(简短地)学习计算机科学时,它有点像荒凉的西部。 他们给我们带来了问题,我们入侵了它,直到它起作用为止。 大多。 除了通过运行程序并将输出与期望的输出作为一个整体式clusterf…clusterfantasy进行比较之外,无法验证系统。 集群朋友。 你明白了。

In the late 90s, extreme programming became a thing, and suddenly there were test frameworks to use. Fast forward nearly 20 years, and we have mature, extensible and fast frameworks with true code isolation so we can test without side effects and languages that make this easy as well such as our friend Javascript.

在90年代后期,极限编程成为一回事,突然间就有了要使用的测试框架。 快进将近20年,我们拥有成熟,可扩展和快速的框架,具有真正的代码隔离功能,因此我们可以进行测试,而不会产生副作用以及使之如此容易的语言,例如我们的朋友Javascript。

I spent a considerable amount of effort over the years experimenting with different development strategies. Most of the time, I designed code and then wrote tests once I was sure the design was sound enough to begin that work. This was OK, except when it wasn’t, and when it wasn’t, it was catastrophe. I would find that code was actually untestable.

这些年来,我花费了大量的精力尝试不同的开发策略。 大多数时候,我确定自己的声音足以开始这项工作时,我设计了代码,然后编写了测试。 可以,除非不是,如果不是,那就是灾难。 我会发现代码实际上是不可测试的。

A great example is a website I coded using Meteor. Meteor was amazing, and allowed me to go from 0 to 60 with a working, complex website in about a month and a half. It was so simple, tests didn’t even seem necessary. However, I ran into a subtle bug with the way the MongoDB was structured, and now have found 2 or 3 others that I literally cannot fix without a rewrite from scratch. When Meteor introduced testing, it was specific to Meteor, and didn’t make it easy to run tests in multiple browsers, and doesn’t support wallaby at all without a gigantic monolith of a wallaby.js which would need its own unit tests to be sure it works. I literally woke up with nightmares while I was trying to solve this problem.

一个很好的例子是我使用Meteor编码的网站。 流星棒极了,让我在大约一个半月的时间内通过一个工作正常的复杂网站从0上升到60。 它是如此简单,测试似乎根本没有必要。 但是,我在构建MongoDB的方式时遇到了一个细微的错误,现在发现了另外2或3个,如果不从头开始重写,我实际上是无法解决的。 当Meteor引入测试时,它是Meteor特有的,并且没有使在多个浏览器中运行测试变得容易,并且在没有巨大的wallaby.js庞大组件的情况下根本不支持wallaby。确保它有效。 当我试图解决这个问题时,我确实梦night以求地醒了。

So for this project, I decided to write tests from the beginning, experimenting with Test-driven design. What I found is that writing tests first causes the design to change from the beginning, and my code became simpler. I started to develop an intuitive suspicion when code became too complex, and began erasing entire swaths of code when the testing became difficult, or complex in any way, then finding much more elegant solutions in half the time after starting from scratch. Here’s the catch: the development pace is about 4 times slower than what I was used to from before. However, I’m not worried about subtle bugs creeping in. I’m not worried about the overall design being brittle. The feeling of confidence is exhilarating and frees me up to dream about solutions instead of putting out fires.

因此,对于这个项目,我决定从一开始就编写测试,并尝试测试驱动的设计。 我发现编写测试首先会使设计从一开始就发生变化,并且我的代码变得更加简单。 当代码变得太复杂时,我开始产生一种直觉的怀疑;当测试变得困难或变得复杂时,我开始擦除整个代码,然后在从头开始的一半时间内找到了更优雅的解决方案。 这就是要抓住的地方:开发速度比我以前的速度慢了大约4倍。 但是,我并不担心会潜入细微的错误。我也不担心整体设计会很脆弱。 自信的感觉令人振奋,使我有更多的梦想去解决方案,而不是扑灭大火。

In addition, I refactor often, as I learn more about the system I’m designing and discover subtle incorrect assumptions about how the libraries and database I’m using actually work or my design choices actually work. I find myself erasing and re-purposing code very often. Because I’m erasing and moving things so often, and the lines of code of my tests are 14 times longer than the lines of actual code, in order to develop at anything resembling a reasonable pace, the tests need to be surgically designed to avoid blowing up on any little change. I learned this the hard way.

此外,随着我​​对正在设计的系统的更多了解,我会经常进行重构,并且发现关于我正在使用的库和数据库如何实际工作或我的设计选择实际如何工作的细微错误假设。 我发现自己经常擦除和重新使用代码。 因为我经常擦除和移动东西,并且测试的代码行比实际代码的行长14倍,为了以合理的速度进行开发,因此需要通过手术设计避免炸毁任何微小的变化。 我经过惨痛的教训才学到这个。

Most of my early tests had subtle dependencies on design choices that frankly didn’t matter to that test. I would find myself going through and copy/pasting changes to 20 or more tests when I would refactor. So I sat down and looked at ways of removing any dependencies from the tests, and wound up with the system this article describes.

我的大部分早期测试对设计选择都有微妙的依赖性,坦率地说,对测试而言无关紧要。 当我重构时,我会发现自己正在经历并复制/粘贴对20个或更多测试的更改。 因此,我坐下来研究了从测试中删除所有依赖项的方法,并总结了本文介绍的系统。

Each test only tests 1 thing, usually just a single line of code, and no change to any other area of the component being tested will cause a test to fail, except for compile errors or other easily fixable mistakes. My hope is that my mistakes early on will help you to avoid them. With that in mind, let’s dive in!

每次测试仅测试一件事情,通常仅测试一行代码,对任何其他被测试组件区域的更改都不会导致测试失败,除非编译错误或其他易于修复的错误。 我希望我的早期错误会帮助您避免这些错误。 考虑到这一点,让我们开始吧!

开始 (Starting off)

Let’s begin with a list of the tools we’ll be using, and where to find them.

让我们从我们将要使用的工具以及在哪里找到它们的列表开始。

Here is the list of imports we’ll need:

这是我们需要的进口清单:

We’ll be using standard imports from React, Redux, the bindings between React and Redux, as well as the context for React-DnD and its testing backend. Let’s talk about teaspoon.

我们将使用从React,Redux,React和Redux之间的绑定以及React-DnD的上下文及其测试后端的标准导入。 让我们谈谈茶匙。

Teaspoon is a brilliant creation of Jason Quense that allows testing React components as if they were HTML using a jQuery-like interface. It allows testing whether specific properties were passed, easily triggering events with mock data, and also easily setting properties or state of React components. It’s beautiful. Go read the docs. See you in 15 minutes.

Teaspoon是Jason Quense的出色创造,它允许使用类似jQuery的界面将React组件当作HTML进行测试。 它允许测试是否传递了特定的属性,轻松地通过模拟数据触发事件,还可以轻松地设置React组件的属性或状态。 真漂亮。 去阅读文档。 15分钟后见。

从头开始构建测试助手 (Building the test helper from scratch)

Welcome back!

欢迎回来!

The next step is constructing the basic component testing interface. What we need to do first is set up the component rendering code. I have experimented with both teaspoon’s shallow and deep rendering, and concluded that there is never a good reason to use shallow rendering.

下一步是构建基本的组件测试接口。 我们首先需要设置组件渲染代码。 我对茶匙的浅渲染和深渲染进行了实验,并得出结论,从来没有充分的理由使用浅渲染。

The primary issue with shallow rendering is that in a week, you will have forgotten that you used shallow rendering when you refactor something, and your test will break for no good reason, forcing you to waste 15 minutes trying to figure out why until you realize all you have to do is turn on deep rendering and the test will pass.

浅层渲染的主要问题在于,一周之内,您会忘记在重构某些东西时使用了浅层渲染,并且测试将无缘无故地中断,从而迫使您浪费15分钟试图找出原因,直到您意识到您要做的就是打开深度渲染,测试将通过。

So, we begin with a simple renderComponent function which we will use to render any React component, and wrap it in teaspoon so that we can test things about it:

因此,我们从一个简单的renderComponent函数开始,我们将用它来渲染任何React组件,并将其包装在茶匙中,以便我们可以测试一下它:

This code accepts a React Component class or function, and passes in any properties specified in the props. Simple.

该代码接受一个React Component类或函数,并传入props中指定的任何属性。 简单。

Next, we need to wire up Redux so we can handle state:

接下来,我们需要连接Redux,以便我们处理状态:

Now we can write tests to ensure properties are being used in our components:

现在,我们可以编写测试以确保在组件中使用属性:

More about how to write effective tests later. For now, let’s continue with the next problem.

有关稍后如何编写有效测试的更多信息。 现在,让我们继续下一个问题。

Soon, you will need to test changing a property. Unfortunately, this is difficult to do because rendering is asynchronous, and tests are synchronous by nature. Fortunately, there is a way to force rendering to be synchronous. Without going into too much detail on why, using a higher order component to wrap your component class and setting props using local React state will force a re-render so that we can test for the effect of a property change. Here is the new renderComponent:

很快,您将需要测试更改属性。 不幸的是,这很难做到,因为渲染是异步的,并且测试本质上是同步的。 幸运的是,有一种方法可以强制渲染是同步的。 无需过多说明为什么,使用更高阶的组件来包装您的组件类并使用本地React状态设置props将强制重新渲染,以便我们可以测试属性更改的效果。 这是新的renderComponent:

Next, we need to think about how to test container components. In my experience, it is tempting to try to test the internal React class HTML output in much the same manner, but it is far more maintainable to test what the container actually does. Container classes have 1 job: transforming redux state into react component properties.

接下来,我们需要考虑如何测试容器组件。 以我的经验,尝试以几乎相同的方式测试内部React类HTML输出是很诱人的,但是测试容器的实际作用要容易得多。 容器类有一项工作:将redux状态转换为react组件属性。

Using teaspoon, you can actually verify that containers take a slice of state and reliably create the component names and values that the internal React component is expecting, without needing to know anything about the internals of the React component inside the container test.

使用茶匙,您实际上可以验证容器是否具有状态片,并可靠地创建内部React组件所期望的组件名称和值,而无需了解容器测试内有关React组件内部的任何信息。

The most notable exception to this fact is that we also need to test actions. In order to do this, it is best to test for either the change of state that is expected upon a dispatched action, or to check to see if the action was sent.

这个事实最明显的例外是,我们还需要测试操作。 为了做到这一点,最好测试派发的动作所期望的状态变化,或者检查动作是否已发送。

To test state, we need to access the state after an action is triggered, and we can do that by using the redux store’s getState() method. So, we will need to return the store if needed.

为了测试状态,我们需要在触发动作之后访问状态,我们可以使用redux存储的getState()方法来完成。 因此,如果需要,我们将需要退货。

The most decoupled method is to check to see if the correct action was sent. To do this, we will need to create a redux middleware that simply logs all actions into an array that can then be used to check actions sent. Let’s modify renderComponent to make these two scenarios possible:

最分离的方法是检查是否发送了正确的操作。 为此,我们将需要创建一个redux中间件,该中间件将所有操作简单地记录到一个数组中,然后可以使用该数组检查发送的操作。 让我们修改renderComponent以使这两种情况成为可能:

The question of how to use this more advanced functionality will be addressed in the second half of this article, where I will describe how to use this helper to write effective and limited tests.

在本文的下半部分将解决如何使用此更高级的功能的问题,在此我将描述如何使用此助手来编写有效且有限的测试。

The last portion of the test helper is quite simple, and just adds support for React-DnD. All we need is to wrap everything inside a DragDropContext with the test backend:

测试助手的最后一部分非常简单,仅添加了对React-DnD的支持。 我们需要做的就是将所有内容包装在带有测试后端的DragDropContext中:

Now, we can access the Draggable manager and backend with Draggable.getManager() and Draggable.getManager().getBackend() as documented in the React-DnD docs. Note that the .prototype is required in order to access getManager().

现在,我们可以使用React-DnD文档中记录的Draggable.getManager()Draggable.getManager().getBackend()访问Draggable管理器和后端。 请注意, .prototype是访问getManager()所必需的。

At this stage, we are ready to explore how to use this test helper effectively.

在此阶段,我们准备探索如何有效使用此测试助手。

使用助手编写出色的测试 (Writing great tests using the helper)

There are a few key principles that inform how I write tests:

有一些关键原则可以指导我如何编写测试:

  1. don’t repeat anything

    不要重复任何事情
  2. use clever boilerplate

    使用聪明的样板
  3. test properties and actions separately

    分别测试属性和动作

Here is an example of a component being tested that has both properties and actions. The example uses sinon to do testing of callbacks:

这是同时具有属性和操作的被测试组件的示例。 该示例使用sinon进行回调测试:

Note that if you want to test changing a property in order to test a life cycle method such as shouldComponentUpdate, you should use teaspoon’s props() method. The same is true of state() for testing local state changes.

请注意,如果您要测试更改属性以测试生命周期方法(如shouldComponentUpdate),则应使用teaspoon的props()方法。 用于测试本地状态更改的state()也是如此。

The test above uses a few unifying ideas:

上面的测试使用了一些统一的想法:

  1. even renderComponent() is abstracted into a 2 new methods, one for testing properties (render), and one for testing actions (make).

    甚至renderComponent()也抽象为2种新方法,一种用于测试属性(渲染),另一种用于测试动作(make)。
  2. A generic set of default properties is specified so that there will be no React warnings for any tests, allowing each test to focus on a single property (aptly named “generic.”)

    指定了一组通用的默认属性,以便任何测试都不会出现React警告,从而使每个测试都可以专注于单个属性(适当地称为“通用”)。
  3. There is no testing of visual properties/css/html directly beyond ensuring that basic scaffolding is present

    除了确保存在基本脚手架外,没有直接测试视觉属性/ css / html
  4. The test focuses on ensuring external input to the component is correct. Each property is tested, and each action is tested.

    该测试的重点是确保组件的外部输入正确。 测试每个属性,并测试每个动作。
  5. CSS/HTML is only used to locate the place where properties are situated within the virtual DOM of the component

    CSS / HTML仅用于在组件的虚拟DOM中定位属性所在的位置

We will extend these ideas to test connected react-redux containers next.

接下来,我们将扩展这些思想以测试连接的react-redux容器。

测试Redux连接的容器组件 (Testing Redux-connected Container Components)

The most important thing a redux component does is transform state into properties and callbacks into redux actions. Using the renderComponent we created, we can easily test this:

redux组件所做的最重要的事情是将状态转换为属性,并将回调转换为redux操作。 使用我们创建的renderComponent,我们可以轻松地对此进行测试:

Here, we can test exclusively that our connecting container is transforming state into the properties we expect, and is dispatching the actions we expect. In most of my earlier tests, I would check to make sure actions modified the state (the second method in the doSomething test), but this actually duplicates the work of ensuring that your reducers are reducing. Thus, if you refactor a reducer, you have to update every test for a connected container. This can make refactoring slower.

在这里,我们可以专门测试连接容器是否将状态转换为我们期望的属性,并分派我们期望的动作。 在我以前的大多数测试中,我都会检查以确保操作修改了状态(doSomething测试中的第二种方法),但这实际上与确保减速器进行还原的工作重复。 因此,如果重构减速器,则必须为连接的容器更新每个测试。 这会使重构变慢。

Instead, checking for which actions were dispatched is completely decoupled from the reducer, and simply verifies the contract for the connected component.

取而代之的是,检查调度了哪些操作的操作与reducer完全分离,并且只需验证所连接组件的合同即可。

There are drawbacks to decoupling, in that a change to a reducer could have multiple side effects in containers. If you are aware of this, then you are fine. In a multi-developer shop, or when you develop amnesia a few months later, you may want to have everything that is connected to the reducer fail when a change is made.

去耦存在缺点,因为对异径管的更换可能在容器中产生多种副作用。 如果您知道这一点,那就很好。 在一家多开发人员的商店中,或者几个月后发生失忆症时,您可能希望在进行更改时使连接到reducer的所有设备失效。

测试Redux-Saga动作处理程序 (Testing a redux-saga action handler)

If you wish to test a redux-saga generator, that is very thoroughly documented on the redux-saga site. If you find that too confusing, and want an article about how I do it (or why I chose redux-saga), please reply in the comments.

如果您想测试redux-saga生成器,则在redux-saga站点上有非常详尽的记录。 如果您觉得这太令人困惑,并且想发表一篇关于我如何做(或为什么我选择redux-saga)的文章,请在评论中回复。

One of the patterns I have run into in this application that requires redux-saga is turning a single action into multiple actions. The use case for this in my scheduling application is the listener I wrote for updating the CouchDB instance when records are changed by the client. In order to implement proper conflict detection while records are independently updated online, each record needs to have the same id. Thus, unique ids are generated based on the names of the composers of pieces the kids could play. When a composer’s name is updated, every instance of the use of that composer must also be updated. Thus, a single action spawns many new actions. Because of the potential for missed actions and inconsistent state in the database, I wrote a saga to listen for the modification action, and then send out many new actions to make the changes needed.

我在这个需要redux-saga的应用程序中遇到的一种模式是将一个动作变成多个动作。 在我的调度应用程序中,此用例是我编写的用于在客户端更改记录时更新CouchDB实例的侦听器。 为了在独立地在线更新记录时实现正确的冲突检测,每个记录需要具有相同的ID。 因此,根据孩子可以演奏的乐曲的作曲家的名字生成唯一的ID。 当更新作曲家的姓名时,也必须更新该作曲家使用的每个实例。 因此,单个动作会产生许多新动作。 由于数据库中可能遗漏操作和状态不一致,因此我写了一个传奇来侦听修改操作,然后发出许多新操作来进行所需的更改。

Thus, when clicking a save button, an action is sent out that is not handled by any reducer. Instead, it is intercepted by the saga, and transformed into the many individual actions that are needed. It also updates the database.

因此,当单击“保存”按钮时,将发出未由任何减速器处理的动作。 取而代之的是,它被传奇故事拦截,并转化为许多需要的单独动作。 它还会更新数据库。

This could have been implemented with middleware, but redux-saga makes handling all of the asynchronous portions of the work so easy, it doesn’t make sense to re-invent the wheel when a few lines of code can do the same work and be more easily tested. How do we test this? We could set up a mock redux-saga listener for the action in our test helper, but how long do we wait for the saga to complete before we test our state to ensure it was modified? How do we prevent the saga from actually trying to modify a database? A nightmare ensues!

这可能已经用中间件实现了,但是redux-saga使处理工作的所有异步部分变得如此容易,当几行代码可以完成相同的工作并且重新创建代码时,重新发明轮子是没有意义的更容易测试。 我们如何测试呢? 我们可以在测试帮助器中为操作设置一个模拟的redux-saga侦听器,但是在测试状态以确保修改其状态之前,我们需要等待多长时间才能完成saga? 我们如何防止传奇实际上尝试修改数据库? 一场噩梦接!而至!

Long story short: in this case, all we need to verify is that the connected component is dispatching the action that will be intercepted by the redux-saga. A separate test can be used to verify the correctness of the saga itself. Once that is confirmed, then we can be sure that the action will work.

简而言之:在这种情况下,我们需要验证的是所连接的组件正在调度将由redux-saga拦截的操作。 可以使用单独的测试来验证传奇故事本身的正确性。 一旦确认,我们就可以确定该动作将起作用。

Thus, we can use the log middleware we created in our test helper to see if the action we intended to send is in fact sent. Easy!

因此,我们可以使用在测试帮助器中创建的日志中间件来查看是否确实发送了要发送的操作。 简单!

测试React-DnD (Testing React-DnD)

React-DnD needs a drag and drop context to work without errors, even if you’re not doing anything with drag and drop in the test. If you have wrapped any of your components, you will still want to be able to test the basic functionality of that component, and our test helper makes this possible. You can test the basic functionality using our test helper, and ignore the drag and drop, then test the drag and drop in a separate test using the methods laid out in the documentation for React-DnD if needed. Very easy!

即使您在测试中不执行任何操作,React-DnD也需要拖放上下文才能正常工作。 如果包装了任何组件,您仍将希望能够测试该组件的基本功能,而我们的测试助手将使其成为可能。 您可以使用我们的测试助手来测试基本功能,而无需拖放,然后根据需要使用React-DnD文档中列出的方法在单独的测试中测试拖放。 好简单!

The only gotcha I found is that it is not intuitive how to mock dragging and dropping, and the documentation is spotty at best. Here is a sample test from my real project showing how to test the drag and drop interaction. Note that the components in question are dumb components, and the property book and clear are callbacks supplied by the redux-connected container component. I’ll include the container even though it isn’t actually tested by these tests to make that clearer. Also note the creation of helper functions to extract the sourceId and targetId from the component directly, defined as the source and target functions in Slot.test.js.

我发现的唯一陷阱是,如何模拟拖放操作并不直观,而且文档充其量也充斥着杂乱无章的内容。 这是我真实项目中的示例测试,显示了如何测试拖放交互。 请注意,所讨论的组件是哑组件,而属性bookclear是由redux连接的容器组件提供的回调。 我将包含该容器,即使这些测试并未对其进行实际测试以使其更加清晰。 还要注意创建辅助函数以直接从组件中提取sourceId和targetId,在Slot.test.js中将其定义为source函数和target函数。

我使用的工具挽救了我的编程生涯 (Tools I use that have saved my programming life)

If you haven’t invested in wallaby.js or WebStorm, you’re missing out. Having instantaneous test results, instantaneous test coverage visible line by line as well as your continuous integration with karma is a godsend. I use karma on BrowserStack to verify the code doesn’t break in mobile and desktop browsers, and wallaby to quickly verify that my code works and is covered prior to commit.

如果您没有投资wallaby.js或WebStorm,那么您会错失良机。 具有瞬时测试结果,逐行可见的瞬时测试覆盖范围以及您与业力的持续集成真是天赐之物。 我在BrowserStack上使用业力来验证代码在移动浏览器和台式机浏览器中不会中断,并在鼠袋中快速验证我的代码是否有效并在提交之前被覆盖。

Here is a sample wallaby.js I use for my project, with support for CSS modules in tests:

这是我用于项目的样例wallaby.js,它在测试中支持CSS模块:

In addition, if you aren’t using React-Storybook, you’re missing out. It’s the best way to develop your visual look of the app with some assurance it will work. It systemizes manual testing, the last element of any successful app, and recent versions can even automate that testing, although I have not used that personally.

另外,如果您不使用React-Storybook ,那么您会错过。 这是在确定应用程序正常运行的情况下发展应用程序视觉外观的最佳方法。 它将人工测试系统化,这是任何成功应用程序的最后一个要素,尽管我个人没有使用过,但最新版本甚至可以自动化该测试。

结论 (Conclusion)

There are many different ways of testing. If you’re developing a complex application in react-redux, you’ll want to take a hard look at how to decouple your components so that they can be easily tested. Fortunately, with this simple test helper and principles for test design, testing is easy, and you can refactor with limited side effects on unrelated tests, making development fast, and change easy.

有许多不同的测试方法。 如果要在react-redux中开发复杂的应用程序,则需要仔细研究如何解耦组件,以便可以轻松地对其进行测试。 幸运的是,有了这个简单的测试助手和测试设计原理,测试就很容易了,并且您可以重构对无关测试的副作用,从而使开发快速且容易进行。

Happy coding! Please leave a comment if you have other systems I haven’t mentioned, I’m always looking for new ideas. Also, if something I’ve said is unclear or incomplete, please ask and I’m happy to try to clarify.

编码愉快! 如果您有我未提及的其他系统,请发表评论,我一直在寻找新的想法。 另外,如果我说的话不清楚或不完整,请询问,我们很乐意澄清。

Click that pretty heart button too, if you enjoy the article!

如果您喜欢这篇文章,也请单击该漂亮的心形按钮!

翻译自: https://www.freecodecamp.org/news/testing-react-and-redux-with-redux-saga-and-reactdnd-whew-dedebcbd78dd/

 类似资料: