目录
- 4.React中的TDD和单元测试
- 4.1 什么是TDD
- 4.2 React环境中配置Jest
- 4.3 Enzyme的配置
- 4.4 利用TDD的方式来开发项目
- 4.4.1 利用TDD的方式开发Header组件
- 4.4.2 TodoList的测试代码编写
- 4.4.3 Header 组件样式新增及快照测试
- 4.4.4 通用的测试代码提取封装
- 4.4.5 UndoList的实现
- 4.4.6 给UndoList添加样式
- 4.4.7 测试代码优化
- 4.4.8 UndoList编辑功能实现
- 4.4.9 UndoList编辑功能实现2
- 4.4.10 CodeCoverage代码覆盖率
- 4.5 TDD和单元测试总结
- 5.BDD和集成测试
TDD的开发流程:(Red-Green development)
1.编写测试用例;
2.运行测试,测试用例无法通过测试;
3.编写代码,使测试用例通过测试
4.优化代码,完成开发
5.重复上述步骤
TDD优势
1.长期减少回归bug;
2.代码质量良好(组织,可维护性)
3.测试覆盖率高,一般测试覆盖率在80%,90%,不能做到100%
4.错误测试代码不容易出现
接下来通过一个TodoList项目来了解TDD的流程
执行下面 命令
指定这个版本会有问题,npm install create-react-app@3.0.1 -g
jest-react目录下面有个隐藏的git文件夹,我们可以使用git来管理代码。
通过下面的命令创建一个分支
执行npm run eject命令之前执行下面命令,不然会报错
其实脚手架已经集成了jest命令,执行npm run eject命令会把隐藏的配置项都弹射出来
jest有2个要求,有一个是通过git来管理,还有一个是要安装jest,这里已经都满足了。
jest的配置项但可以写在文件 jest.config.js中,也可以写在package.json文件中(该文件中有配置项叫’jest”)
关于jest配置项的介绍后面再补充。
使用默认保存的格式化工具保存jsx形式的react代码,格式会有问题,
解决方法:右下角,把语言模式 改成
删除脚手架里面的冗余代码,只剩下App.js代码,index.js代码和App.test.js文件。
App.js代码如下
App.test.js文件代码如下:
如下代码,可以测试渲染的组件的内容元素
前端单元测试中如果直接去写这种面向DOM的测试用例,是有局限性的,在做前端单元测试的时候,有的时候想要测试组件的state和prop状态是否正确,不仅要测试DOM的展开,还要测试组件里面的数据细节,直接通过DOM做测试就没办法实现我们对组件内部数据做测试的需求了。
面向DOM的测试用例有局限性,有时候要测试测试一个组件的prop和state(组件上的状态),DOM的测试只能让我们测试组件的渲染,所以airbnb公司的enzyme的引入就是为了解决这个问题。
enzyme其实是对 ReactDOM.render做了一些包装,提供了一些额外的方法供我们调用,是我们能够对组件进行更灵活的测试。
首先安装enzyme,可以去github上搜索airbnb公司的enzyme,(https://github.com/enzymejs/enzyme),查看相关介绍
如何配置呢?在测试文件中添加下面的内容
将这段代码直接复制到App.test.js文件中去,这样测试用例中就可以使用enzyme了。
enzyme其实是对 ReactDOM.render做了一些包装,有了Enzyme,就不需要ReactDOM了,删除相关的代码
如下代码:
接下来试试shallow的其他方法,修改App.js内容,给div添加title属性,如下代码:
如何测试呢?
上面的测试代码有个小问题,就是测试用例的代码和要测试代码耦合很高,上面是通过div的className属性来获取元素的,如果我们觉得div的className不太合适的,会对其进行修改,修改之后测试代码也要跟着修改,代码是耦合的,这样就会比较麻烦。可以用下面的方式来解决这个问题。给要测试的div添加一个专门的测试属性:
App.js代码如下:
App.test.js代码如下:
这样的过程就是测试代码和要测试代码解耦的过程。
Enzyme里面有jest-enzyme,下面链接里面可以看到一些API方法
https://github.com/FormidableLabs/enzyme-matchers/tree/master/packages/jest-enzyme
这个链接里面有很多可以使用的比较简单的API方法,如下所示,之前写的代码,可以简化成下面的形式,但是发现运行的时候报错了,toExist未定义
这时需要安装Jest-enzyme
在使用的时候,还需要在package.json文件中引入jest-enzyme,如下所示,github连接里面也有介绍
重启启动npm run test命令后,就可以使用这些简化语法的API了。
Jest-enzyme 里面是有很多匹配器的,可以使用这个里面的匹配器
可以优化为下面的形式
接下来我们看看mount方法
其实这里组件测试也可以使用toMatchSnapshot() 匹配器,这个匹配器适用于测试组件内容不发生改变的组件,当组件内容更新之后,再更新snapshot。
接下来通过一个TodoList的实例来理解TDD的开发流程
4.4.1 利用TDD的方式开发Header组件
在项目的src目录下新建containers文件夹,在containers文件夹下面新建TodoList文件夹,在其目录下新建index.js文件,index.js文件代码如下
App.js文件代码如下:
一般测试文件会在同级目录下面建立,一般我们会在containers/TodoList同级目录下建立__ tests 文件夹,然后其目录下建立unit文件夹,表示是该组件的单元测试文件代码。
在TodoList文件夹下面建立components文件夹,文件目录下放与TodoList相关的代码,在这个目录下面新建Header.js文件,代码如下
在unit目录下建立Header.js文件,表示是Header.js文件的测试用例。
Header组件实现了输入文本框的内容,按下回车键后,可以追加到代办列表中
TDD的开发流程是写测试用例,测试用例是失败的,然后写代码让测试用例通过,最后再优化代码的过程。
首先来开发测试用例,Header组件里面有一个input组件,Header组件的测试代码如下:
tests __文件夹下面的Header.js文件代码如下:
执行npm run test命令发现测试用例没有通过,然后我们去写源代码让测试用例通过,这就是TDD的开发流程
修改components目录下面的Header.js文件代码,代码如下,这样我们编写的测试用例就可以通过了。
第2个测试用例是往input框里面输入内容时,input框里面的内容会发生变化。下面代码的第2个测试用例执行会报错,
Header是一个受控组件,所以其value值是输入值来决定的,修改Header.js文件内容,使测试用例通过
第3个测试用例是往input框里面输入内容时,input框里面的内容会发生变化,如下的测试用例,第3个测试用例未通过,
修改Header.js文件,添加Input控件的onChange方法,使测试用例通过。
我们不仅可以测试state的内容,还可以测试input标签的属性等等。如下的代码:
接下来编写其他的测试用例,当在input框里面输入内容时候,点击回车,我们希望把input框里面的内容存入到最外层的TodoList组件中,这个测试用例怎么写呢?如下代码
接着我们补充没有实现的功能,让测试用例通过,Header.js代码如下:
测试代码还可以进一步优化,使用 toHaveBeenLastCalledWith,如下代码所示:
最后写完的Header.js测试代码如下
Header.js的源代码如下
4.4.2 TodoList的测试代码编写
在unit目录下新建文件TodoList.js,来编写TodoList的单元测试
TodoList.js的测试文件代码如下:通过一个个编写测试用例,让测试用例通过完成我们的代码开发过程
index.js的源代码如下:
测试代码通过之后,我们也不知道界面UI写的是否正确,修改index.js代码如下:
以上过程可以看出,利用TDD的方式编写TodoList组件,能够发现代码中的大部分bug。
4.4.3 Header 组件样式新增及快照测试
在TodoList文件夹下面新建文件style.css,代码内容如下:
在index.js文件里引入css文件
import React, { Component } from ‘react’;
import Header from ‘https://blog.51cto.com/u_16213693/components/Header’
在Header.js文件里面添加一些样式
当Header组件的样式写完之后,我们不希望它做频繁的变化,可以写个快照测试,如下代码
之后UI发生变化之后,快照测试不会通过,提醒我们验证一下修改后的样式是否正确。
4.4.4 通用的测试代码提取封装
1.相似代码提取
2.enzyme引入文件封装到一个文件,这个文件配置到package.json文件中的setUpFilesAferEnv配置项里面
上面的例子中虽然额外写了一些测试代码,但是当项目里面新添加一个功能时,需要验证以前的老代码,如果有自动化测试代码,只要确保这些测试用例通过就可以了,如果没有自动化测试代码的话,老代码手动点击回归测试的时间会比较多,非常耗费人力。
4.4.5 UndoList的实现
当实现了文本框输入,输入回车之后,需要将内容添加到undoList中,当点击确认后,内容添加到已经完成项。
接下来我们通过TDD的形式来 实现UndoList。
在components文件目录下新建文件UndoList.js文件,在测试目录unit目录下新建文件UndoList.js,测试文件代码如下所示,每编写一个测试用例,然后再写源代码,
UndoList.js代码如下:
上面的测试代码就实现了UndoList内部的单元测试,删除的功能就放在TodoList来做,测试代码如下
index.jsx代码如下:
4.4.6 给UndoList添加样式
4.4.7 测试代码优化
每个组件测试用例的描述都比较长,可以将每个test测试用例放到describe里面,describe的名称是组件的名称,这样测试代码看起来,可读性就会更高一些。
4.4.8 UndoList编辑功能实现
当编辑undoList的每项时,可以让其变成编辑状态,当失焦或者按下回车时,保存为修改后的名称。
我们存储的undoList数据结构是一个数组,只用于展示,并不是识别input框,所以这里要改变其数据结构,识别是不是input框的状态。
这样添加数据项的时候也应该修改一下数据结构,index.jsx代码如下
修改代码的数据结构之后,UndoList的测试文件代码也要跟着修改,如下代码
UndoList.js代码如下
修改数据结构后,修改相关报错代码,当单元测试全部通过的时候,页面却是挂的;
使用TDD加上单元测试方式的问题:真正的数据结构或者组件内容发生变化的时候,需要回头重新修改测试用例;因为测试用例里面用了大量耦合的数据;当有需求变更的时候,会导致之前的测试用例不可用。
即便所有的单元测试用例都通过了测试,也无法保证项目在浏览器上可以正确无误地运行,因为单元测试测试的是每个组件,并没有将每个组件集成在一起做测试,这样每个组件是好用的,但是合在一起是否好用不知道。
4.4.9 UndoList编辑功能实现2
该小节实现当输入框失去焦点时,就 不是输入框,而是显示状态了。通过先写测试用例,然后写代码的方式实现这个功能。
4.4.10 CodeCoverage代码覆盖率
看看测试代码覆盖了多少业务逻辑代码
在package.json文件里添加一个命令coverage,执行npm run coverage命令就可以看到测试用例的覆盖率了,可以index.html中详细看出,coverage这2行命令都可以被成功执行。
TDD和单元测试是2个不同的概念,TDD也可以和集成测试在一起。
当写函数库的时候,非常适合用单元测试来写。
业务场景下,单元测试的劣势很明显,业务代码使用集成测试更好地保证项目的质量。
BDD(Behavaior Driven Development) 行为驱动开发
先写代码,再写测试代码
TDD
1.先写测试再写代码;
2一般结合单元测试使用,是白盒测试;
3.测试重点在代码;
4.安全感第;
5.速度快;
BDD
1.先写代码再写测试;
2.一般结合集成测试使用,是黑盒测试;
3.测试重点在于UI(DOM)
4.安全感高
5.速度慢

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/149828.html