单元测试

作为一个前端程序猿,在日常工作当中可能会遇到定制化地封装想要的组件的情况,此时我们写了很多行的代码,却并没有测试给我们回归,如果只靠我们自己保证质量,难免有漏掉的情况发生,这时单元测试的重要性就体现了。

当然了,在一些大的项目当中代码逻辑的正确性和功能性也尤为重要,此时完成一些功能后,我们也需要对其进行单元测试保证质量。

当我们按照整理好的需求还有设计文档完成了概要设计、文档书写和开发,在最后回归的时候可以按照文档和功能性对组件进行一定的测试,看看我们最终是否按照文档完成所有的功能和确保 JavaScript 代码的正确性。

接下来我们仔细看看单元测试

提到单元测试很多人会想到 Jest,那它有什么特性呢?

  • Jest 是 Facebook 开源的 JavaScript 测试框架,只需很少的配置,还能够根据需求进行扩展。

  • Jest 拥有自己独立的进程,最大限度地提高性能。

  • Jest 集成了断言、JSDom、覆盖率报告等开发者所需要的所有测试工具。通过添加 --coverage 标志生成代码覆盖率报告, 无需额外设置。Jest 可以从 整个项目收集代码覆盖面信息,包括未经测试的文件。

  • Jest 拥有良好的文档,提供了易于理解、熟悉且功能丰富的 API 来编写测试用例,并快速地反馈结果。

接下来,我们来看看如何安装和使用:

安装

使用 yarn 安装

yarn add --dev jest

使用 npm 安装

npm install --save-dev jest
配置

package.json 中增加:

{
  "scripts": {
    "test": "jest"
  }
}

常见命令:

{
  "nocache": "jest --no-cache", //清除缓存
  "watch": "jest --watchAll", //实时监听
  "coverage": "jest --coverage",  //生成覆盖测试文档
  "verbose": "npx jest --verbose" //显示测试描述
}

jest.config.js 添加配置项

export default {
  testMatch: ['<rootDir>/lib/**/__test__/**/*.[jt]s?(x)'],
  moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'node'],
  collectCoverage: false, // 是否收集测试时的覆盖率信息(默认是false,同package配置的--coverage参数)
  preset: 'ts-jest',
  transform: {
    '^.+\\.jsx?$': 'babel-jest',
    '^.+\\.tsx?$': 'babel-jest',
  },
  globals: {
    'ts-jest': {
      tsConfig: {
        jsx: 'react',
      },
    },
  },
  testEnvironment: 'jsdom',
  rootDir: ' ',
};
  • testMatch 识别哪些文件是测试文件

  • moduleFileExtensions 测试文件的类型

  • testEnvironment 测试环境,默认为jsdom,可修改为 node

  • rootDir 当前目录,一般是 package.json 所在的目录

运行

最后使用 yarn test 或者 npm run test 运行

API

测试用例:

test(name, fn, timeout)

下面是一个测试用例,判断是否相等

test("this is a test",()=>{
  expect({a:1}).toBe({a:1})
})

断言

当你想要测试一个值的时候,可以使用 expect

判断相等

toBe 是否等于

用来比较数字和字符串,不能用于浮点数

expect(value).toBe(value)
toBeCloseTo 是否等于

用于浮点数比较,numDigits 指检查小数点后几位数

expect(value).toBeCloseTo(number, numDigits?)

现在,来看看下面的一个例子:

// 结果是 Fails
expect(0.2 + 0.1).toBe(0.3); 

// 下面是正确的写法
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);

在 JavaScript 中,0.2 + 0.1 等于 0.30000000000000004。

toEqual 是否等于

用来比较数字、字符串、对象和数组,会递归的检查对象的所有属性和属性值是否相等,如果进行类型比较时,可以使用 toEqual

expect(value).toEqual(value)
toBeNull 是否等于 null

只匹配 null

expect(value).toBeNull()
toBeUndefined 是否等于 undefined

只匹配 undefined

expect(value).toBeUndefined()

包含

用来判断是否有包含关系

toHaveProperty 是否有对应属性

keyPath 代表对象的属性,value 代表属性的值

expect(value).toHaveProperty(keyPath, value?)
toContain 是否包含对应的值

括号里可以是数组或是字符串,生产当中可以用来检查数组中是否包含某一项。

expect(value).toContain(item)
toMatch 是否匹配对应的值

括号里可以是正则或是字符串

expect(value).toMatch(regexp | string)
toMatchObject 是否匹配对应的值

用来匹配对象和数组

expect(value).toMatchObject(object)

逻辑

用于逻辑判断,比如:大于、小于、是否为真等。

toBeTruthy 是否为真

可用来匹配 if 语句为真

expect(value).toBeTruthy()
toBeFalsy 是否为假

可用来匹配 if 语句为假

expect(value).toBeFalsy()

在 JavaScript 中,只有 6 种是假值,分别是:false,0,'',null,undefined 和 NaN。 其它的都是真值。

toBeGreaterThan 大于

使用 toBeGreaterThan 来进行大于的比较

expect(value).toBeGreaterThan(number | bigint)
toBeGreaterThanOrEqual 大于等于

使用 toBeGreaterThanOrEqual 来进行大于等于的比较

expect(value).toBeGreaterThanOrEqual(number | bigint)
toBeLessThan 小于

使用 toBeLessThan 来进行小于的比较

expect(value).toBeLessThan(number | bigint)
toBeLessThanOrEqual 小于等于

使用 toBeLessThanOrEqual 来进行小于等于的比较

expect(value).toBeLessThanOrEqual(number | bigint)

取反

测试不等于某个值的情况,not 后面可以是其它的断言

expect(value).not.toBe(value)

下面是一些使用的例子:

const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    area: 20,
    wallColor: 'white',
    'nice.oven': true,
  },
  'ceiling.height': 2,
};

expect(houseForSale.bath).toBe(true);
expect(houseForSale.bedrooms).toEqual(4);
expect(houseForSale.kitchen).toBeNull();
expect(houseForSale.hello).toBeUndefined()

expect(houseForSale).toHaveProperty('bath');
expect(houseForSale).toHaveProperty('bedrooms', 4);
expect(houseForSale.kitchen.amenities).toContain('oven');
expect(houseForSale.kitchen.wallColor).toMatch(/white/);

expect(houseForSale.bath).toBeTruthy();
expect(houseForSale.bath).toBeFalsy();
expect(houseForSale.kitchen.area).toBeGreaterThan(18);
expect(houseForSale.kitchen.area).toBeLessThan(30);

expect(houseForSale).not.toHaveProperty('pool');

分组

describe(name, fn)

分组可以包含多个测试用例,即多个 test():

describe("component test",()=>{
    test("this is a test",()=>{
      ......
    })
    test("this is b test",()=>{
      ......
    })
    ......
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容