react单元测试_React测试简介

react单元测试

Let’s write unit test cases for our react applications build with create-react-app.

让我们为用 create-react-app 构建的React应用程序编写单元测试用例

Testing can be done in different ways, we can test an application by running it and then checking it manually whether everything is working fine or not. Another method is automated testing, in which we write test cases to test tiny fragments of our application code, say one unit, and thus called Unit testing.

测试可以通过不同的方式进行,我们可以通过运行应用程序然后手动检查它是否一切正常来测试应用程序。 另一种方法是自动测试,其中我们编写测试用例来测试应用程序代码的微小片段(例如一个单元),因此称为单元测试。

📝 A small note on Test driven development

on关于测试驱动开发的小笔记

Any code that has no tests is a legacy code -Michael Feathers

没有测试的任何代码都是遗留代码-Michael Feathers

Test driven development (TDD) helps a developer to avoid legacy codes. While working with large application or with a big team, it is not very easy to remember all the requirements and logic associated with different components. So if someone add a new functionality to an existing component of a test driven application, it is very easy to implement the changes without having a prior knowledge of all responses and dependencies, by simply checking whether it passes all test cases or not.

测试驱动开发(TDD)帮助开发人员避免使用遗留代码。 在使用大型应用程序或大型团队时,要记住与不同组件相关的所有需求和逻辑并非易事。 因此,如果有人在测试驱动的应用程序的现有组件中添加了新功能,则只需简单地检查是否通过所有测试用例就可以很容易地实现更改,而无需事先了解所有响应和依赖项。

测试工具🛠 (Tools for Testing 🛠)

For testing react application we mainly use two tools, jest and enzyme.

为了测试React应用程序,我们主要使用两个工具, jest

Jest is a JavaScript test runner that lets you access the DOM via jsdom. It is responsible for executing test and provide validation library. Jest is already installed in an app created with create-react-app.Enzyme is an open-source testing framework maintained by Airbnb . Enzyme will help us render React components in testing mode.

Jest是一个JavaScript测试运行程序,可让您通过jsdom访问DOM。 它负责执行测试并提供验证库。 Jest已安装在使用create-react-app创建的应用程序中。 是由Airbnb维护的开源测试框架。 酶将帮助我们在测试模式下渲染React组件。

建立环境 (Setting up our Environment)

Before we start few packages needs to be installed. As mentioned above, Jest would be already installed in applications created using create-react-app.

在开始之前,需要安装一些软件包。 如上所述,Jest已经安装在使用create-react-app创建的应用程序中。

We need install Enzyme along with an adapter corresponding to react version we used. I’m using react 16, hence I installed enzyme-adapter-react-16. npm install --save enzyme enzyme-adapter-react-16

我们需要安装酶以及与我们使用的React版本相对应的适配器。 我使用的是react 16,因此我安装了enzyme-adapter-react-16npm install --save enzyme enzyme-adapter-react-16

Let’s have a look into the dependencies of our package.json file to see which all packages need to be installed for successfully running our test cases.

让我们看一下package.json文件的依赖关系,以查看需要安装哪些所有软件包才能成功运行我们的测试用例。

{
“babel-jest”: “20.0.3”,
“enzyme”: “^8.1.0”,
“enzyme-adapter-react-16”: “^1.0.1”,
“jest”: “20.0.4”,
“react”: “^16.0.0”,
“react-dom”: “^16.0.0”,
“react-test-renderer”: “^16.0.0”
}

开始吧.. (Let’s start..)

Now as we got some idea on testing and the required packages, its time to get our hands dirty.

现在,当我们对测试和所需的软件包有了一些了解时,就该开始动手了。

测试功能组件 (Testing functional components)

A functional component also known as stateless component, is used only for presentation purpose. It takes props as argument and return a valid JSX element. Since it does not contain complex logic, it is very easy to test. The below code is a functional component, Person.js, that renders a paragraph with some text received as props.

功能组件也称为无状态组件,仅用于表示目的。 它以props作为参数,并返回有效的JSX元素。 由于它不包含复杂的逻辑,因此非常易于测试。 下面的代码是一个功能组件Person.js,它呈现了一个段落,其中包含一些文本作为props

import React from 'react' const Person = ( props ) => (  
<p>{ props.children }</p>
) export default Person

To test this component, we have to create a test file Person.test.js,

为了测试该组件,我们必须创建一个测试文件Person.test.js,

import React from 'react';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Person from './Person'configure({ adapter: new Adapter() }) describe('Person', () => {
it('should render children inside a p tag', () => {
const wrapper = shallow(<Person>This is Person</Person>)
const Person = wrapper.find('p')
expect(Person).toHaveLength(1)
expect(paragraph.text()).toEqual('This is Person')
})
})

Jest has couple of methods to define a test.

Jest有几种定义测试的方法。

describe(): It is a function with two arguments, first argument gives the description of test bundle. Usually we give name of the component as first argument. Second argument is a normal ES6 arrow function, which contains all test cases associated with that component.

describe() :这是一个具有两个参数的函数,第一个参数给出测试包的描述。 通常我们将组件的名称作为第一个参数。 第二个参数是普通的ES6箭头函数,其中包含与该组件关联的所有测试用例。

it(): it is another function that allows us to write individual test cases. It also has two arguments. First one is a string which describes the test and second argument is a function that defines the test.

it()it是另一个函数,允许我们编写单个测试用例。 它还有两个参数。 第一个是描述测试的字符串,第二个参数是定义测试的函数。

expect(): The expect function is used every time you want to test a value. Usually it is used along with a "matcher" function to assert something about a value.

Expect() :每次要测试一个值时,都会使用expect函数。 通常,它与“ matcher ”函数一起使用以断言关于值的某些内容。

In order to test the component, we need to create an instant of the component, as it would be rendered in real DOM. For that we use Enzyme, it allows us to render a unit standalone.For this we need to import a named export called configure from enzyme package, and a default export from enzyme-adapter package. After that we have to pass a new instance of adapter to configure function.Enzyme package provide another function called shallow. It renders a JSX element passed as argument. Shallow has two alternatives, Full DOM Rendering and Static Rendering.

为了测试组件,我们需要创建组件的实例,因为它将在真实DOM中呈现。 为此,我们使用Enzyme,它使我们可以独立渲染一个单元。为此,我们需要从酶包导入一个名为configure的命名导出,并从酶适配器包导入一个默认导出。 在此之后,我们不得不适配器的新实例传递给配置function.Enzyme包提供了一种称为另一个功能。 它呈现作为参数传递的JSX元素。 Shallow有两种选择, Full DOM RenderingStatic Rendering

After running test with npm test, react check whether our code meet all expectations, and based on that we get the test result.

在使用npm test运行测试之后,做出React以检查我们的代码是否满足所有期望,并基于此获得测试结果。

具有条件渲染的功能组件 (Functional component with conditional rendering)

In this section we deal with a slightly more complex app, which render child component based on some condition.Here we have a Persons.js file, that render three <Person> component if the value of isData is true, else it renders two <Person> components.

在本节中,我们处理一个稍微复杂一点的应用程序,该应用程序将根据某些条件呈现子组件。这里有一个Persons.js文件,如果isData的值为true,则呈现三个<Person>组件,否则呈现两个<Person>组件。

import React from ‘react’;
import Person from ‘./Person/Person’;const Persons = ( props ) => (
{props.isData
? <Person>Welcome {props.name}</Person>
: null}
{!props.isData
? <Person>Your data is invalid</Person>
: <Person>You have valid data</Person>}
);export default Persons;

Each test cases are independent of others, so if we want to set some state that will be used by many tests we need to repeat it in all test cases. beforeEach() is a global function provided by jest, which receives a function as argument and runs it before every test cases. To display components conditionally based on props value, we have to change it, for that we use setProps() method, this method inject props value into components.

每个测试用例都彼此独立,因此,如果我们想要设置许多测试将使用的某种状态,则需要在所有测试用例中重复该状态。 beforeEach()是jest提供的全局函数,它接收一个函数作为参数并在每个测试用例之前运行它。 要根据props值有条件地显示组件,我们必须对其进行更改,因为我们使用setProps()方法,该方法将props值注入组件。

import React from 'react';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Persons from './Persons';
import Person from './Person/Person';configure({adapter: new Adapter()});describe('Persons', () => {
let wrapper;beforeEach(() => {
wrapper = shallow(<Persons />);
});it('should render two <Person /> elements if data is invalid', () => {
expect(wrapper.find(Person)).toHaveLength(2);
});it('should render three <Person /> elements if data is valid', () => {
wrapper.setProps({isData: true});
expect(wrapper.find(Person)).toHaveLength(3);
});
});

To check the number of occurrence of <Person> we use the property toHaveLength(), it check if the array returned by find() contains given number of elements.

为了检查<Person>的出现次数,我们使用属性toHaveLength(),它检查find()返回的数组是否包含给定数量的元素。

测试状态组件 (Testing Stateful components)

Stateful components are class based components, which contain state, and functions to handling various events. The code below shows a stateful component, that renders a button and a child component based on the value of received prop. Let’s see how can we test it.

有状态组件是基于类的组件,其中包含状态和处理各种事件的功能。 下面的代码显示了一个有状态组件,该组件根据接收到的prop的值呈现一个按钮和一个子组件。 让我们看看如何测试它。

import React, {Componet} from 'react';
import DetailComponent from '../DetailComponent/DetailComponent;class DetailContainer extends Component {state = { clicked: false };
constructor(props) {
super(props)
}
clickHandler = () => {
this.setState({ clicked: !this.state.clicked });
}
let details = this.props.isDetail?<DetailComponent/>: null;
render() {
return (
{details}
<button onClick={this.clickHandler}>
{this.state.clicked ? 'Clicked' : 'Click'}
</button>
)
}}
export default DetailContainer;

In the test file below, we simulate a click on the button and see if the button text has changed.

在下面的测试文件中,我们模拟了按钮的单击并查看按钮文本是否已更改。

describe('DetailContainer', () => {    const wrapper = shallow(<DetailContainer />);    it('should render a button', () => {
expect(wrapper.find('button')).toHaveLength(1);
});
it('should render a button with "Clicked" as text after the button clicked for the first time', () => {
wrapper.find('button').simulate('click');
expect(wrapper.find('button').text()).toEqual('Clicked');
});
it('should render "Click" as button text if button is clicked again', () => {
wrapper.find('button').simulate('click');
expect(wrapper.find('button').text()).toEqual('Click');
});
});
})

We can check the above functionality by directly accessing the event handler.

我们可以通过直接访问事件处理程序来检查上述功能。

it('should change "clicked" variable in state', () => {
expect(wrapper.state('clicked')).toBe(false);
wrapper.instance().clickHandler();
expect(wrapper.state('clicked')).toBe(true);
});

As we done earlier for functional component, here we can access the props and check conditional rendering of child components.

正如我们之前对功能组件所做的那样,在这里我们可以访问道具并检查子组件的条件渲染。

it('should render <DetailComponent/> when isDetail is true', () => {
wrapper.setProps({isDetail: true});
expect(wrapper.find(DetailComponent)).toHaveLength(1);
});

摘要 (Summary)

The above examples give us an introduction on testing in react. We can dive deep into testing but, when we go deeper, our test get more complex. One thing we need to take care is, do not test complex dependencies and external libraries. If you want to test external libraries use mock data and responses, otherwise it is very difficult to test it in normal workflow. So while testing we need to focus on isolated units such as reducer functions and functional components, check whether our page re-render when props changes, also check conditional outputs by providing different values. Happy coding 😀👍

以上示例向我们介绍了React测试。 我们可以深入测试,但是,当我们更深入时,我们的测试就会变得更加复杂。 我们需要注意的一件事是,不要测试复杂的依赖关系和外部库。 如果要测试外部库是否使用模拟数据和响应,则很难在正常工作流程中对其进行测试。 因此,在测试时,我们需要专注于隔离的单元(例如化简函数和功能组件),检查是否在props更改时重新渲染页面,并通过提供不同的值来检查条件输出。 快乐编码😀👍

翻译自: https://medium.com/@annumariajosephv/an-introduction-to-react-testing-2ae49147a250

react单元测试

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值