乐趣区

关于前端:卓越工程实践之前端高质量单测

简介:高单测覆盖率不能防止改变引发,小的改变引发就可能带来大的线上问题。
image.png

作者 | 范喆 (六瓶)
起源 | 阿里开发者公众号

高单测等于高质量?
笔者负责的 npm 包是 ICBU 信天翁低代码平台渲染引擎,160+ 利用 600+ 页面基于该引擎开发,内网日 npm 下载 1K+。通过不懈努力(CV),终于把单测提到了 95%。

然而,尽管在覆盖率上取得了一些数据的扭转,但作为开发者,想要的并不是数据上的完满,而是它真的完满(没 BUG)。作为一个高频援用的底层库,改变一行代码都能够影响到用户意想不到的 bug。

高单测覆盖率不能防止改变引发,小的改变引发就可能带来大的线上问题。

写好单测
issue= 单测
每一个 issue 都有它命中注定的一个单测
在咱们的我的项目中,用 issue 来治理用户需要。用户每发现一个问题都能够到咱们指定仓库中去提 issue,新增的 issue 触发机器人在钉钉群里艾特对应批改人,修复后机器人告诉创建人。

image.png

在软件工程中,对单元测试的形容是“针对每一个单元的测试,以确保每个模块能失常工作为指标”。

在咱们行覆盖率和分支覆盖率都很高的状况下,还须要有新的机制保障模块更稳固。除去那些框架还没摸索到的业务场景,怎么样保障当初用户的肯定没有问题?

于是有了 issue 即单测。

在当初的 issue 运作机制下,保障每一个单侧都有对应的 issue。在仓库中新增了脚本 tnpm run create-issue。

// package.json
“scripts”: {

"create-issue": "node ./script/issue_dev/createIssueTem.js",

}

// createIssueTem.js
/**

  • 疾速创立 issue 示例
    */

const path = require(‘path’);
const execSync = require(‘child_process’).execSync;
const args = process.argv.slice(2);

const issueID = args[0];

if (!issueID) {
console.error(‘ 须要输出 issue id 能力运行 ’);
process.exit();
}

const demoTarget = path.resolve(__dirname, ../../demo/issue_${issueID});
const demoSrc = path.resolve(__dirname, ../template/demo/base.md);

const testTarget = path.resolve(__dirname, ../../test/issues-cov/${issueID});
const testSrc = path.resolve(__dirname, ../template/test/*);
const specTarget = path.resolve(__dirname, ../../test/issues-cov/${issueID}/app.spec.tsx);

execSync(mkdir ${demoTarget});
execSync(cp ${demoSrc} ${demoTarget}/);
execSync(sed -i '''s/issueID/${issueID}/g' ${demoTarget}/base.md);

execSync(mkdir ${testTarget});
execSync(cp ${testSrc} ${testTarget});
execSync(sed -i '''s/issueID/${issueID}/g' ${specTarget});

console.log(创立 ${issueID}胜利 );
在公布前把对应的 demo 做删除

// prebuild
// 构建前删除 issue 的 demo
const fs = require(‘fs’);
const path = require(‘path’);
const ENV = process.env.BUILD_ENV == ‘cloud’;

function removeDir(dir) {
let files = fs.readdirSync(dir);
for (var i = 0; i < files.length; i++) {

let newPath = path.join(dir, files[i]);
let stat = fs.statSync(newPath);
if (stat.isDirectory()) {
  // 如果是文件夹就递归上来
  removeDir(newPath);
} else {
  // 删除文件
  fs.unlinkSync(newPath);
}

}
fs.rmdirSync(dir); // 如果文件夹是空的,就将本人删除掉
}

fs.readdir(‘./demo’, (err, path) => {
if (err) {

console.log(err);

}
path.forEach((pathItem) => {

if (pathItem.includes('issue') && ENV) {removeDir(`./demo/${pathItem}`);
  console.log(` 删除 ${pathItem}`);
}

});
});
当咱们运行 tnpm run create-issue 123456,帮咱们创立对应 issue 123456 的单测 +demo,复用同一个 template 内容,能够在浏览器端看到 demo,也能够在 vs code 中间接编写单测内容。

image.png

在 demo 中,能够间接点击 gitlab 链接跳转到对应 issue。

image.png

这里拿一个简略的 issue 做演示:

image.png

对应的原子单测

describe(‘116193’, () => {
it(‘should work’, async () => {

const wrapper = mount(<App />);
await sleep(10);
wrapper.mount();
expect(Object.keys(A)).toMatchSnapshot();
expect(A.hasApplied).toBeDefined();
return wrapper.unmount();

});
});
单测非常简单,尽管只有两句 expect,但这两句是只为这个 issue 存在,强行 cp。

issue 惟一单测笼罩,保障 0 改变引发。

在业界一些优良的开源框架也是有同样的 issue 即单测的案例,比方 mobx。

image.png

单测 = 文档
原子类单测能够极大水平保障代码稳定性,组件类能够形容开发者冀望的用法。

单测即文档

image.png

闭环积淀反哺
除此之外,issue 的 Milestone 代表对应 npm 版本:

// changelog

1.24.0

  1. 【FEAT】列表过滤提供相似表单的校验模式 #115827(cover by test)
  2. 【FEAT】model 内置属性应该不可枚举 #116193(cover by test)
  3. 【FEAT】冀望提供 ref 注解,不便平台侧做辨别 #116364
  4. 【Bug】watch 在正则的模式下,调用 silent validate 会导致 autoValidate 生效 #116242(cover by test)
    issue 的最好归宿就是 cover by test。钉钉 -> issue -> npm changelog 互相对应,做到每个单测可溯源。

image.png

笔者负责的框架曾经推广了一年,再回顾一下。值得思考的是,重头设计一次架构,是否能完满的解决当初的这些 issue。

这些 issue 和单测都是走过的足迹,当初咱们曾经积攒单测 170+,其中 60+ issue 原子类单测。不能保障 0BUG。但可预感的是让用户释怀用,不会有改变引发。单测是品质的守门神,帮忙框架做好用户预期,一步步更持重的前行。

最初
写单测最好的工夫是我的项目开始前,其次是当初。

“阿里灵杰”问天引擎电商搜索算法大赛

原文链接:http://click.aliyun.com/m/100…

本文为阿里云原创内容,未经容许不得转载。

退出移动版