天天看点

React 测试入门教程

react的组件结构和jsx语法,不适用传统的测试工具,必须有新的测试方法和工具。

本文总结目前react测试的基本做法和最佳实践,手把手教你如何写react测试。

React 测试入门教程

然后,打开 http://127.0.0.1:8080/,你会看到一个 todo 应用。

React 测试入门教程

接下来,我们就要测试这个应用,一共有5个测试点。

应用标题应为"todos" todo项的初始状态("未完成"或"已完成")应该正确 点击一个todo项,它就反转状态("未完成"变为"已完成",反之亦然) 点击删除按钮,该todo项就被删除 点击添加按钮,会新增一个todo项

这就是说,同样的测试用例至少有两种写法,本文都将介绍。

官方测试工具库的写法 enzyme的写法

我们知道,一个react组件有两种存在形式:虚拟dom对象(即<code>react.component</code>的实例)和真实dom节点。官方测试工具库对这两种形式,都提供测试解决方案。

shallow rendering:测试虚拟dom的方法 dom rendering: 测试真实dom的方法

shallow rendering (浅渲染)指的是,将一个组件渲染成虚拟dom对象,但是只渲染第一层,不渲染所有子组件,所以处理速度非常快。它不需要dom环境,因为根本没有加载进dom。

首先,在测试脚本之中,引入官方测试工具库。

然后,写一个 shallow rendering 函数,该函数返回的就是一个浅渲染的虚拟dom对象。

上面代码中,<code>const app = shallowrender(app)</code>表示对<code>app</code>组件进行"浅渲染",然后<code>app.props.children[0].props.children</code>就是组件的标题。

你大概会觉得,这个属性的写法太古怪了,但实际上是有规律的。每一个虚拟dom对象都有<code>props.children</code>属性,它包含一个数组,里面是所有的子组件。<code>app.props.children[0]</code>就是第一个子组件,在我们的例子中就是<code>h1</code>元素,它的<code>props.children</code>属性就是<code>h1</code>的文本。

首先,需要修改<code>shallowrender</code>函数,让它接受第二个参数。

下面就是测试用例。

官方测试工具库的第二种测试方法,是将组件渲染成真实的dom节点,再进行测试。这时就需要调用<code>renderintodocument</code> 方法。

现在,每次运行<code>npm test</code>,<code>setup.js</code> 就会包含在测试脚本之中一起执行。

上面代码中,第一步是将<code>app</code>渲染成真实的dom节点,然后使用<code>scryrendereddomcomponentswithtag</code>方法找出<code>app</code>里面所有的<code>li</code>元素。然后,取出第一个<code>li</code>元素里面的<code>button</code>元素,使用<code>testutils.simulate.click</code>方法在该元素上模拟用户点击。最后,判断剩下的<code>li</code>元素应该少了一个。

这种测试方法的基本思路,就是找到目标节点,然后触发某种动作。官方测试工具库提供多种方法,帮助用户找到所需的dom节点。

可以看到,上面这些方法很难拼写,好在还有另一种找到dom节点的替代方法。

如果一个组件已经加载进入dom,<code>react-dom</code>模块的<code>finddomnode</code>方法会返回该组件所对应的dom节点。

上面代码中,<code>finddomnode</code>方法返回<code>app</code>所在的dom节点,然后找出第一个<code>li</code>节点,在它上面模拟用户点击。最后,判断<code>classlist</code>属性里面的<code>todo-done</code>,是否出现或消失。

第五个测试用例,是添加新的todo项。

上面代码中,先找到<code>input</code>输入框,添加一个值。然后,找到<code>add todo</code>按钮,在它上面模拟用户点击。最后,判断新的todo项是否出现在todo列表之中。

<code>finddomnode</code>方法的最大优点,就是支持复杂的css选择器。这是<code>testutils</code>本身不提供的。

它提供三种测试方法。

<code>shallow</code> <code>render</code> <code>mount</code>

上面代码中,<code>shallow</code>方法返回<code>app</code>的浅渲染,然后<code>app.find</code>方法找出<code>h1</code>元素,<code>text</code>方法取出该元素的文本。

关于<code>find</code>方法,有一个注意点,就是它只支持简单选择器,稍微复杂的一点的css选择器都不支持。

在上面代码中,你可以看到,<code>render</code>方法与<code>shallow</code>方法的api基本是一致的。 enzyme的设计就是,让不同的底层处理引擎,都具有同样的api(比如<code>find</code>方法)。

上面代码中,<code>find</code>方法返回一个对象,包含了所有符合条件的子组件。在它的基础上,<code>at</code>方法返回指定位置的子组件,<code>simulate</code>方法就在这个组件上触发某种行为。

下面是enzyme的一部分api,你可以从中了解它的大概用法。

<code>.get(index)</code>:返回指定位置的子组件的dom节点 <code>.at(index)</code>:返回指定位置的子组件 <code>.first()</code>:返回第一个子组件 <code>.last()</code>:返回最后一个子组件 <code>.type()</code>:返回当前组件的类型 <code>.text()</code>:返回当前组件的文本内容 <code>.html()</code>:返回当前组件的html代码形式 <code>.props()</code>:返回根组件的所有属性 <code>.prop(key)</code>:返回根组件的指定属性 <code>.state([key])</code>:返回根组件的状态 <code>.setstate(nextstate)</code>:设置根组件的状态 <code>.setprops(nextprops)</code>:设置根组件的属性

(完)

继续阅读