前言
前段时间写了一篇关于移动端运行JS脚本的文章: 记录一次在移动端运行JS脚本的试验, 里面提到关于调试的部分:搭建一个Vue
项目用于脚本的调试。但经过一段时间的实践发现,该方案弊端较多:
- 模块之间较难做整合。
- 调试是通过
eval
注入的脚本打包产物,虽说也可在浏览器控制台调试,但不够直接。(其实是移动端写多了不太习惯在浏览器调试。。。) Vue
毕竟与视图有关联,每次新增脚本都需要编写额外的Vue
部分代码,增加了成本。
说白了就是懒。。。所以针对调试这件事,笔者重新思考了一下。JS脚本的验证主要分为两个部分:逻辑正确和环境适配。环境的话,只要JS引擎的适配性强,一般不会有大问题。毕竟最终还会使用Babel
进行编译,这也是借鉴前端开发的场景得出的结论。所以大部分问题会出现在逻辑上,再结合上面提到的问题,最后笔者打算通过Jest
做一个由Typescript
编写的单元测试。
Jest单元测试
流程
这里将之前的浏览器层替换成了Jest
单元测试。由于是模拟层,所以关于脚本中需要原生注入的对象都会在单元测试中进行模拟。
Jest搭建
这里笔者采用的是Jest + Babel + Typescript
的结构。Babel负责Typescript的编译,以及JS版本的转换问题。
npm install jest @types/jest babel-jest --save-dev
npx jest --init
初始化后,会生成一个jest.config.js
,用于Jest
的配置,这里没有特殊的配置所以没有修改。编译过程中会自动读取babel.config.js
,如果测试与实际打包的Babel配置有区别则需要特别区分。更多的信息可以查看Jest文档。
简单的测试代码
Jest环境就绪后,就需要一个.(spec|test).ts
的文件作为单元测试的case文件。以下是以上篇文章提到的Demo代码为基础编写的单元测试。这里主要分为两端的测试,Android、iOS。
describe('Test', () => {
beforeEach(() => {
jest.resetModules()
});
test('Android', () => {
process.env.OS = 'Android'
// 模拟原生对象注入
const dbObj = require('./exports/db').default
dbObj.loadDB('./test/sqlite/test.db', 'database')
const deviceInfoObj = require('./exports/deviceInfo').default
deviceInfoObj.loadDeviceInfo('Android')
// 注入脚本
require('../src/Test')
// 脚本内容执行
const inferInterface = global['test']
inferInterface.testFetchOne()
dbObj.closeDB('database')
})
test('iOS', () => {
process.env.OS = 'iOS'
// 模拟原生对象注入
const dbObj = require('./exports/db').default
dbObj.loadDB('./test/sqlite/test.db', 'database')
const deviceInfoObj = require('./exports/deviceInfo').default
deviceInfoObj.loadDeviceInfo('iOS')
// 注入脚本
require('../src/Test')
// 脚本内容执行
const inferInterface = global['test']
inferInterface.testFetchOne()
dbObj.closeDB('database')
})
afterEach(() => {
delete process.env.OS
})
})
复制代码
test
函数可以理解为每个测试case,这里分为Android、iOS。具体的流程就和移动端运行时大同小异了:
- 原生对象注入(这里是创建一个JS对象添加到
global
进行模拟)。 - 注入脚本(依赖脚本代码)。
- 脚本内容执行。
ps:这里没有用太多Jest
的api,具体细节可查看Jest官方文档。
运行效果:
在控制台运行后,可查看每个case的运行状况,如果是出错也会有对应的堆栈。
结合VSCode
还可以结合VSCode
进行断点调试。
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest",
"program": "${workspaceFolder}/module-script/node_modules/.bin/jest",
"args": [
],
"cwd": "${workspaceRoot}/module-script",
"outputCapture": "std",
}
]
}
复制代码
创建一个launch.json
执行jest命令,接下来就能愉快的断点调试脚本了。
最后
以上就是关于脚本的单元测试内容。采用这种方式可以很好的解决随脚本复杂度提高带来的调试成本,也是比较符合移动端开发习惯的。
最后再贴一下Demo地址:xcyoung/mobile-js-engine-exsample (github.com)