Jest

Jest是 Facebook 的一套开源的 JavaScript 测试框架, 它自动集成了断言、JSDom、覆盖率报告等开发者所需要的所有测试工具,是一款几乎零配置的测试框架。并且它对同样是 Facebook 的开源前端框架 React 的测试十分友好。

1. 全局安装

yarn global add jestnpm install jest --global
这样就可以通过命令行直接运行Jest
yarn与npm对比

2. 结合babel使用jest

安装所需的依赖:
yarn add --dev babel-jest @babel/core @babel/preset-env

还需安装@babel/plugin-transform-runtime@babel/runtime,不然测试会报错

  • .babelrc文件配置
    可以在工程的根目录下创建一个babel.config.js文件用于配置与你当前Node版本兼容的Babel
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "current"
      }
    }]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}
  • package.json配置
  "jest": {
    // moduleNameMapper:  一种正则表达式到模块名的映射,匹配到的文件的内容可以是空的
    // 可以通过该参数,来mock一些图片,css等静态资源文件
    // 因为我们在测试的时候实际上是不太需要这些文件的,但是有需要引入它作为环境上的依赖。
    "moduleNameMapper": {
      "^vue$": "vue/dist/vue.common.js"
    },
    // moduleFileExtensions: 让jest知道你需要测试覆盖的文件的扩展名都是什么。
    "moduleFileExtensions": [
      "js",
      "vue"
    ],
    //  transform: 简单来说就是转换器,正则匹配到的文件可以通过对应模块的转换器来解决一些未来版本语法时可以使用它。通过正则来匹配文件,为匹配到的文件使用对应的模块
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
      ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
    }
  }

注意: jest24不支持babel6

  • 如要使用jest24,可以将babel升级到版本7
  • 如果babel不能升级到7,那么就使用jest23
  • babel不能升级到7,要使用jest24,那么就将babel-test版本锁在23

3. 匹配器

常用匹配器:

  • 普通匹配器: toBe, toEqual
  • Truthiness: toBeNull,toBeUndefined,toBeDefined,toBeTruthy,toBeFalsy
  • 数字: toBeGreaterThan,toBeGreaterThanOrEqual,toBeLessThan,toBeLessThanOrEqual,toBeCloseTo
  • 字符串:toMatch
  • 数组:toContain

4. 测试用例

Jest会自动找到项目中所有使用.test.js文件命名的测试文件并执行,通常我们在编写测试文件时遵循的命名规范:测试文件的文件名 = 被测试模块名 + .test.js,例如被测试模块为functions.js,那么对应的测试文件命名为functions.test.js。

快照测试

只要想确保UI不会意外更改,快照测试是非常有用的工具。(其实就是运行测试的时候,把结果存一份,之后阔以用来对比,对比不上就测试不通过)

// Snapshot Testing
it('will fail every time', () => {
  const user = {
    createdAt: new Date(),
    id: Math.floor(Math.random() * 20),
    name: 'LeBron James',
  }

  // expect () 返回一个"期望"的对象
  expect(user).toMatchSnapshot()
})

The first time this test is run, Jest creates a snapshot file that looks like this:

exports[`will fail every time 1`] = `
Object {
  "createdAt": 2019-12-13T02:11:50.571Z,
  "id": 1,
  "name": "LeBron James",
}
`;

Jest使用pretty-format对快照文件进行了处理,当代码在审查期间,会让代码快照变成让人类可阅读的文件。
jest --updateSnapshot更新快照

测试异步

单元测试的核心之一就是测试方法的行为是否符合预期,在测试时要避免一切的依赖,将所有的依赖都mock掉

  1. 回调:一种最常见的异步编程模式
    错误示例:
  // 不要这么做!
  //  一旦 fetchData 执行完毕,测试随即完毕,而不会等待 callback 回调的执行。
test('the data is peanut butter', () => {
  function callback(data) {
    expect(data).toBe('peanut butter')
  }

  fetchData(callback)
})

正确示例:

// 使用一个名为 done 的参数,Jest 会一直等待 done 回调的执行,一旦 done 回调执行完毕,测试即完成。
// 如果 done 一直没有被回调,那么测试失败。
test('the data is peanut butter', done => {
  function callback(data) {
    expect(data).toBe('peanut butter');
    done()
  }

  fetchData(callback)
})
  1. Promise
    只需要在测试中返回一个 promise,Jest 会自动等待 promise 被解析处理,如果 promise 被拒绝,那么测试失败。
test('the data is peanut butter', () => {
   // expect.assertions 来验证一定数量的断言被调用。 否则一个fulfilled态的 Promise 不会让测试失败
  expect.assertions(1)
  return fetchData().then(data => {
    expect(data).toBe('peanut butter');
  })
})

test('the fetch fails with an error', () => {
  expect.assertions(1);
  return fetchData().catch(e => {
    expect(e).toMatch('error')
  })
})

5. 在webpack项目中用

  • (1)如果你的项目使用了babel转换,具体的配置,参见上述第二个菜单
    (2)如果你的项目没有使用babel转换,可以配置Jest的transform参数来进行转换
  • 接下来,让我们配置Jest,使其优雅地处理资源文件,如样式表和图像。 通常,这些文件在测试中无足轻重,因为我们可以安全地mock他们。 然而, 如果你使用CSS模块,那么最好是给你的类名查找模拟一个代理。
// package.json
{
  "jest": {
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
    }
  }
}

6. 在react项目中使用

  • (1) 使用create react app:
    它已经包含了 可用的 Jest! 您只需要添加 react-test-renderer 来渲染快照。
    yarn add --dev react-test-renderer
    (2) 不使用create react app:
    yarn add --dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer

  • 配置

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