测试 — Vue.js

使用vue-cli 脚手架时,选择单元测试(jest)

  • jest的配置 ```jsx // node_modules/@vue/cli-plugin-unit-jest/presets/default/jest-preset.js module.exports = { moduleFileExtensions: [ // 可以省略的模块扩展名 ‘js’, ‘jsx’, ‘json’, // tell Jest to handle .vue files ‘vue’ ], transform: { // 模块转换器 // process .vue files with vue-jest ‘^.+\.vue$’: require.resolve(‘vue-jest’), // .vue 模块使用 vue-jest 转换 ‘.+\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$’: require.resolve(‘jest-transform-stub’), // css 等模块使用 jest-transform-stub 转换为字符串 ‘^.+\.jsx?$’: require.resolve(‘babel-jest’) // .jsx 模块使用 babel-jest 转换 }, transformIgnorePatterns: [‘/node_modules/‘], // 不转换第三方包资源模块 // support the same @ -> src alias mapping in source code // 支持模块加载路径中的 @ 别名 moduleNameMapper: { ‘^@/(.*)$’: ‘/src/$1’ }, // 测试环境,Jest中的默认环境是通过jsdom的类似于浏览器的环境 // 如果要构建 node 应用,则可以使用 node 选项来使用类似 node 的环境。 // 通过在文件顶部添加 @jest-environment docblock,可以在该文件中指定另一个用于所有测试的环境 testEnvironment: ‘jest-environment-jsdom-fifteen’, // serializer for snapshots

    // 序列化快照 // 对 .vue 组件进行快照测试,快照存储为一个文件,文件内容需要格式化,这里使用 jest-serializer-vue 进行格式化处理 snapshotSerializers: [ ‘jest-serializer-vue’ ],

    // 要测试的文件路径 testMatch: [ ‘/tests/unit//.spec.[jt]s?(x)’, ‘**/tests/.[jt]s?(x)’ ], // 测试的浏览器环境地址 // https://github.com/facebook/jest/issues/6766 testURL: ‘http://localhost/‘,

    // 监视运行测试的插件工具 watchPlugins: [ // 在监视模式下,为 p 方式筛选文件提供交互式选择文件功能 require.resolve(‘jest-watch-typeahead/filename’), require.resolve(‘jest-watch-typeahead/testname’) ] }

``` image.png

  • 当 Jest 加载 .vue.js 文件时,会在正确的转换器中运行,并将文件转换为可在 Node 下运行的 JavaScript 代码。
  • Jest 通过 vue-jest 和 babel-jest 编译一个组件。

Vue Test Utils 通过将它们隔离挂载,然后模拟必要的输入 (prop、注入和用户事件) 和对输出 (渲染结果、触发的自定义事件) 的断言来测试 Vue 组件。

被挂载的组件会返回到一个包裹器内,而包裹器会暴露很多封装、遍历和查询其内部的 Vue 组件实例的便捷的方法。

Wrapper 是一个对象,该对象包含了一个挂载的组件或 vnode,以及测试该组件或 vnode 的方法

mount 和 shallowMount

  • 尽一切努力使用shallowMount,远离mount

    测试是什么

    对于 UI 组件来说,我们不推荐一味追求行级覆盖率,因为它会导致我们过分关注组件的内部实现细节,从而导致琐碎的测试。

    组件测试不应该测什么

    1、单纯测组件模板中的 HTML
    比如,测试组件模板中有几个 divinputbutton,以及元素的 classid 属性等与业务逻辑无关的纯 UI 测试。这里并非说我们不需要关注组件的 UI,而是出于以下几个考量:

  • 使用单元测试测试组件的 UI 会导致测试非常繁琐,为了测试覆盖的全面会导致针对一个组件写出大量的测试,不但降低了开发效率还体验非常差

  • 这种单纯的 UI 测试是非常脆弱的,这类测试和组件模板是强耦合的,一旦我们对 HTML 结构进行调整,测试就会挂掉,这就造成了测试非常难以维护。而实际上我们往往并不关心组件模板中的具体 HTML 结构是怎样的,我们只关心组件呈现出来的样子
  • 像 Jest 等前端测试框架已经提供了快照测试来帮助我们对比修改引起的 UI 变化,并且我们也可以使用Storybook这类工具实现可视化的 UI 测试

2、测试组件的内部方法
如果一些方法只是在组件内部调用其他方法而没有任何暴露给外部的行为(比如更改了组件的 UI、请求外部 API 等),那这些方法是不需要测试的。我们希望一个组件就像一个黑盒一样,我们不关心其内部的处理逻辑而只关注其外部呈现。

组件测试应该测什么

取而代之的是,我们推荐把测试撰写为断言你的组件的公共接口,并在一个黑盒内部处理它。一个简单的测试用例将会断言一些输入 (用户的交互或 prop 的改变) 提供给某组件之后是否导致预期结果 (渲染结果或触发自定义事件)。
比如,对于每次点击按钮都会将计数加一的 Counter 组件来说,其测试用例将会模拟点击并断言渲染结果会加 1。该测试并没有关注 Counter 如何递增数值,而只关注其输入和输出。
该提议的好处在于,即便该组件的内部实现已经随时间发生了改变,只要你的组件的公共接口始终保持一致,测试就可以通过。
这个话题的细节在 Matt O’Connell 一份非常棒的演讲中有更多的讨论。

如何进行组件测试

1、确定业务逻辑
2、确认输入和输出
3、不要超出输入和输出的界限
3、不要测试其它库的功能

参考