1、TDD 测试驱动开发
(Test Driven Development)
TDD三定律
- 1、在编写不能通过的单元测试前,不可编写生产代码。
- 2、只可编写刚好无法通过的单元测试,不能编译也算不通过。
- 3、只可编写刚好足以通过当前失败测试的生产代码。
总的来说就是先写测试再写生产代码,写一个测试就应该立即写它的实现代码。
2、环境安装及准备
(1)模块的引入方式
JavaScript中的模块是可重复使用的代码段,可以从一个程序导出并导入到另一个程序中使用。
module.export = 变量; || module.export = {对象内属性方法}
const 变量 = require('引入的文件相对地址带后缀名.js'); |
ES6引入了一个更灵活,更简单的语法来导出模块:
export default 变量;
export {变量名、对象名、函数};
export {变量名 as 别名、对象名、函数};
import 变量 from '文件相对地址(不要文件后缀)'; |
(2)准备IDE VS code\jest
Jest是 Facebook 的一套开源的 JavaScript 测试框架, 它自动集成了断言、JSDom、覆盖率报告等开发者所需要的所有测试工具,是一款几乎零配置的测试框架。并且它对同样是 Facebook 的开源前端框架 React 的测试十分友好。
准备测试工具安装包:jest
首先,给VScode 安装jest环境,可以自动跑测试代码
2 安装Jest
2.1 初始化package.json
在shell
中输入以下命令,初始化前端项目并生成package.json
:
npm init -y
2.2 安装Jest及相关依赖
在shell
中输入以下命令,安装测试所需要的依赖:
npm install jest
也可以假日babel-jest
、 babel-core
、 regenerator-runtime
、babel-preset-env,
这几个依赖是为了让我们可以使用ES6的语法特性进行单元测试,ES6提供的 import
来导入模块的方式,Jest本身是不支持的。
2.3 添加.babelrc
文件
在项目的根目录下添加.babelrc
文件,并在文件复制如下内容:
{
"presets": ["env"]
}
2.4 修改package.json
中的test
脚本
打开package.json
文件,将script
下的test
的值修改为jest
:
"scripts": {
"test": "jest"
}
这部分安装教程转载自:
链接:https://www.cnblogs.com/xueTP/p/8350572.html
按照流程下来,报错
(1)报错说找不到依赖
Cannot find module '@babel/preset-env' from 'C:\Users\hui..'
就安装了最新的Babel依赖安装bable-preset -env
npm install -D babel-loader @babel/core @babel/preset-env
(2)继续报错
Cannot find module 'babel-preset-env' from 'C:\Users\huihui\Desktop\sum-test'
- Did you mean "@babel/env"?
解决
babel-core和babel-preset-env依赖被替换为@babel/core和@babel/preset-env,因为新版本的Babel7中对官方提供的依赖使用了命名空间@babel
修改.babelrc为bable.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
另外注意:测试文件放在test文件夹中,并且测试文件起名为**.test.js
运行测试用例
npm run test
Demo
(1)实现求和
目录文件如下:
测试代码如下:
// todo a+b=c;
// example:input 1,2 get 3
const sum =require ("../src/sum")
describe("sum",()=>{
test("sum is defined",()=>{
expect(sum).toBeDefined()
}),
test("test should be a function",()=>{
expect(typeof(sum)).toBe('function')
}),
test("input 1,1 got 2",()=>{
expect(sum(1,1)).toBe(2)
}),
test("input 1000,1 got 10001",()=>{
expect(sum(1,1000)).toBe(1001)
}),
test("input 100,1 got 101",()=>{
expect(sum(1,100)).toBe(101)
})
})
运行结果:
(2)实现fizzbuzz游戏
const fb =require ("../src/fizzbuzz")
describe("fb",()=>{
test("fb is defined",()=>{
expect(fb).toBeDefined()
}),
test("fb should be a function",()=>{
expect(typeof(fb)).toBe('function')
}),
test("input 1 got 1",()=>{
expect(fb()[0]).toBe(1)
}),
test("input 3 got fizz",()=>{
expect(fb()[2]).toBe("fizz")
}),
test("input 6 got fizz",()=>{
expect(fb()[5]).toBe("fizz")
}),
test("input 5 got buzz",()=>{
expect(fb()[4]).toBe("buzz")
}),
test("input 15 got fizzbuzz",()=>{
expect(fb()[14]).toBe("fizzbuzz")
})
})
运行结果:
刻意练习 1
实现
Write a function accepting a list of non negative integers,
and returning their largest possible combined number
as a string. For example
given [50, 2, 1, 9] it returns "95021" (9 + 50 + 2 + 1)
given [5, 50, 56] it returns "56550" (56 + 5 + 50)
given 420, 42, 423] it returns "42423420" (42 + 423 + 420)
测试用例:
const hiker = require('./hiker.js');
describe('answer', () => {
it('given [50, 2, 1, 9] it returns "95021"', () => {
expect(hiker.answer([50, 2, 1, 9])).toEqual("95021");
});
it('given [5, 50, 56] it returns "56550"', () => {
expect(hiker.answer([5, 50, 56])).toEqual("56550");
});
it('given [420, 42, 423] it returns "42423420"' ,() => {
expect(hiker.answer([420, 42, 423])).toEqual("42423420");
});
});
代码实现
module.exports = {
answer
};
function answer(ary) {
for (var i = 0; i < ary.length; i++) {
for (var j = i + 1; j < ary.length; j++) {
var oa = ary[i].toString() + ary[j].toString();
var ob = ary[j].toString() + ary[i].toString();
if (oa < ob) {
var temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
}
}
}
var result = ary.toString().replace(/,/g, '');
return result;
}
刻意练习 2
# 字符串计算器,写一个含有Add 方法的 StringCalculator 类,通过分割符分割给定的字符串,返回字符串中所有数字的总和
## Todo(目前分割符只有,和\n)
* '' => 0
* '1' => 1 '2' => 2
* 两个数字,逗号分割 '1,2' => 3 '10,20' => 30
* 两个数字,换行符分割 '1\n2' => 3
* 以任意方式分割字符串 '1\n2,3\n4' => 10
* 不允许使用负数 '-1,2,-3' => 'negatives not allowed: -1,-3'
学到的主要有3点
(1)如何测试错误用例(对于错误的输入,应该报错)
如果使用了负数则报错---》测试用例
test("given '-1,2,-3' should throw error",()=>{
expect(()=>instance.add('-1,2,-3')).toThrowError('negatives are not allowed')
})
代码实现
add(str: string){
if(str.indexof(this.SPLITER[2])>=0){
throw new Error("negtive are not allowed")
}
}
(2)优雅的重构代码
把分割符以及负号符放在一个常量数组中
SPLITER=[',','\n','-']
//处理,逗号
if(str.length>0){
if(str.indexOf(this.SPLITER[0])>=0){
return this.processString(str,this.SPLITER[0])
}
}
//处理\n换行符
if(str.length>0){
if(str.indexOf(this.SPLITER[1])>=0){
return this.processString(str,this.SPLITER[1])
}
}
(3)遍历求和
function processString(str,spliter){
var res=str.split(spliter);
var tempArr=[];
res.forEach(function(item) {
tempArr.push(parseInt(item));
})
return tempArr.reduce(function(total,num){
return total + num;
})
}