说是初探其实我也不知道尝试多少次了,但是每次也就看看那本《Testing Vue.js Applications》,书看了很多遍,真正操作起来就又是另一番光景了。
从简单的node项目开始说起
npm init -y // 初始化一个node项目
npm i -D jest // 安装jest
接下来写一个简单的功能sayHello
// sayHello.js
module.exports = function(name) {
return 'Hello, ' + name;
}
好了让我们测试一下这个函数
// sayHello.test.js
const sayHello = require('./sayHello.js');
test('should return Hello, John', () => {
expect(sayHello('John')).toBe('Hello, John');
});
在jest中所有需要判断的内容都需要用expect函数包裹起来,然后就能
用jest提供了断言函数了,比如上例中的toBe。
jest虽然号称零配置,还是提供了配置文件的jest init.
我们已经被js新的语法给占领了,不使用babel是不可能的了
npm i -D babel-jest @babel/core @babel/preset-env
// babel.config.js
module.exports = {
presets: [[
'@babel/preset-env',
{
targets: {
node: 'current'
}
}
]]
};
默认情况下jest是会自动检测是否有babel.config.js的,如果有就会使用,所以不需要配置jest.config.js中的transform来告诉jest使用babel来处理js文件。安装jest的时候自动安装了babel-jest,所以这个不需要安装了,但是上面babel.config.js中使用了@babel/preset-env需要安装,同时它依赖@babel/core。因此要安装:
npm i -D @babel/core
npm i -D @babel/preset-env
总结一下就是安装jest是babel-jest已经有了,不过babel-jest只是胶水代码用来适配babel,而babel相关的的包需要自己安装,比如@babel/core和@babel/preset-env,如果你还用到了别的preset或plugin,也需要单独安装了。
js在大型项目中使用简直是个灾难,你根本不知道传来传去的对象里面究竟有哪些字段,这时候多希望js是静态语言呀。typescript可以帮助我们。
npm i -D @babel/preset-typescript
// babel.config.js
module.exports = {
presets: [[
'@babel/preset-env',
{
targets: {
node: 'current'
}
}
], '@babel/preset-typescript']
};
However, there are some caveats to using TypeScript with Babel. Because TypeScript support in Babel is transpilation, Jest will not type-check your tests as they are run. If you want that, you can use ts-jest
这段话是从jest的文档中拷贝的
jest.fn返回一个mock function
我们还可以mock返回值
const myMock = jest.fn();
myMock.mockReturnValueOnce(10).mockReturnValueOnce('x').mockReturnValue(true);
名字上看很容易理解
使用jest.mock来mock模块
还有mockImplementation和mockImplementationOnce
mockReturnThis
好了,到此为止jest大概了解了。言归正传,还是回到vue的单元测试吧。
npm i -g vue-cli // vue的脚手架工具
vue init webpack vue-unit // 创建一个vue的项目,选择jest作为单元测试的框架
使用vue脚手架工具创建出来的项目已经帮我们配置好了jest。不过还是有必要了解一下jest的配置。让我们先看一下创建好的项目是怎么配置的。
先看package.json中的unit
jest --config test/unit/jest.conf.js --coverage
它指定了jest的配置文件,在test/unit/jest.conf.js,并且还有代码覆盖率
实话说,这个文件中的东西有点超出了我的知识范围了。刚刚看的jest文档也没看到这些东西,一定是漏看了
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^@/(.*)$': '/src/$1'
},
transform: {
'^.+\\.js$': '/node_modules/babel-jest',
'.*\\.(vue)$': '/node_modules/vue-jest'
},
testPathIgnorePatterns: [
'/test/e2e'
],
snapshotSerializers: ['/node_modules/jest-serializer-vue'],
setupFiles: ['/test/unit/setup'],
mapCoverage: true,
coverageDirectory: '/test/unit/coverage',
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!src/router/index.js',
'!**/node_modules/**'
]
}
这是具体的配置文件的内容https://jestjs.io/docs/en/configuration
创建好的vue项目,运行npm run unit会报错
SecurityError: localStorage is not available for opaque origins
真是一个伤感的事情,解决办法是在jest.conf.js中添加
testURL: 'http://localhost’亲测可用
jest的文档里说testURL默认值是http://localhost,按道理来说不应该报错的呀。真是搞不懂。还有搞不懂的是真是刚使用脚手架创建的vue项目,怎么会这样呢?
算了,搞不懂就先放下吧。
npm run e2e报错了
Error retrieving a new session from the selenium server
Connection refused! Is selenium server started?
{
value: {
message: 'session not created: Chrome version must be between 71 and 75\n' +
' (Driver info: chromedriver=2.46.628402 (536cd7adbad73a3783fdc2cab92ab2ba7ec361e1),platform=Windows NT 10.0.15063 x86_64) (WARNING: The server did not provide any stacktrace information)\n' +
'Command duration or timeout: 997 milliseconds\n' +
"Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:53'\n" +
"System info: host: 'DESKTOP-TK2R2R0', ip: '192.168.56.1', os.name: 'Windows 10', os.arch: 'x86', os.version: '10.0', java.version: '1.8.0_181'\n" +
'Driver info: driver.version: unknown',
error: 'session not created'
},
status: 33
}
表面上看来应该是我的chrome的版本太高了,我的是80.0.3987.149的
解决方案很简单,找到符合自己电脑上chrome版本的chromedriver就好了。官网估计一般人都上不去,我到淘宝镜像上下载的,地址是https://npm.taobao.org/mirrors/chromedriver/,这是一个列表选择自己需要的就好了。我看了看我本机上装的是2.46.628402,这个chromedriver也太老了吧。把下载的文件解压,里面只有一个chromedriver.exe,把这个东西拷贝到项目的node_modules/chromedriver/lib目录下,把原来的那个覆盖掉就行了。再次运行,成功了
vue单元测试使用vue test utils来进行。
如果你创建vue项目时没有指定测试。那么可以用
# unit testing
vue add @vue/unit-jest
# or:
vue add @vue/unit-mocha
# end-to-end
vue add @vue/e2e-cypress
# or:
vue add @vue/e2e-nightwatch
我猜vue add是新脚手架的功能,我的脚手架没有这个功能。
真的是让人难过,使用脚手架创建的项目,竟然没有引入@vue/test-utils,这个不是号称vue官方提供的测试工具吗?自己手动安装吧
npm i -D @vue/test-utils
先定一下组件Item的规格说明
创建Item.vue和Item.spec.js
// src/components/Item.vue
<template>
<div></div>
</template>
<script>
export default {
name: 'Item',
data() {
return {};
}
}
</script>
// unit/Item.spec.js
import Item from '@/components/Item.vue';
import { shallowMount } from '@vue/test-utils';
describe('test Item', () => {
const propsData = {
name: '岁月神偷',
url: 'http://www.baidu.com?word=岁月神偷',
desc: '一部描述时间流逝的电影,发人深思'
};
const wrapper = shallowMount(Item, {
propsData
});
it('should contain name', () => {
expect(wrapper.text()).toContain(propsData.name);
});
it('should contain desc', () => {
expect(wrapper.text()).toContain(propsData.desc);
});
it('should contain an anchor', () => {
expect(wrapper.contains('a')).toBe(true);
});
it('the anchor\'s href should be the url field', () => {
expect(wrapper.find('a').attributes().href).toBe(propsData.url);
});
});
首次运行npm run unit,报错,毫无疑问,这是tdd的第一步red。
第二步写最简单的代码让测试过。
// src/components/Item.vue
<template>
<div>
<a :href="url">{{ name }}</a> {{ desc }}
</div>
</template>
<script>
export default {
name: 'Item',
props: ['name', 'url', 'desc'],
data() {
return {};
}
}
</script>
再次运行npm run unit,成功了。单元测试只进行逻辑的测试,至于样式的测试还是靠自己手动测试了。
至于逻辑复杂的情况怎么进行测试,我还要继续学习。
有用点赞哦,嘻嘻:)