卓越工程实践之—前端高质量单测
发布时间:2022-08-02 12:20:46 所属栏目:云计算 来源:互联网
导读:高单测等于高质量? 笔者负责的npm包是 ICBU信天翁低代码平台渲染引擎,160+应用 600+页面基于该引擎开发,内网日npm下载 1K+。经过不懈努力(CV),终于把单测提到了95%。 然而,虽然在覆盖率上获得了一些数据的改变,但作为开发者,想要的并不是数据上的完
高单测等于高质量? 笔者负责的npm包是 ICBU信天翁低代码平台渲染引擎,160+应用 600+页面基于该引擎开发,内网日npm下载 1K+。经过不懈努力(CV),终于把单测提到了95%。 然而,虽然在覆盖率上获得了一些数据的改变,但作为开发者,想要的并不是数据上的完美,而是它真的完美(没BUG)。作为一个高频引用的底层库,改动一行代码都可以影响到用户意想不到的bug。 高单测覆盖率不能避免改动引发,小的改动引发就可能带来大的线上问题。 写好单测 issue=单测 每一个issue都有它命中注定的一个单测。 在我们的项目中,用issue来管理用户需求。用户每发现一个问题都可以到我们指定仓库中去提issue,新增的issue触发机器人在钉钉群里艾特对应修改人,修复后机器人通知创建人。 图片 在软件工程中,对单元测试的描述是“针对每一个单元的测试,以确保每个模块能正常工作为目标”。在我们行覆盖率和分支覆盖率都很高的情况下,还需要有新的机制保证模块更稳定。除去那些框架还没探索到的业务场景,怎么样保证现在用户的一定没有问题?于是有了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}成功`); 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 在发布前把对应的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}`); } }); }); 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 当我们运行tnpm run create-issue 123456,帮我们创建对应issue 123456的单测+demo,复用同一个template内容,可以在浏览器端看到demo,也可以在vs code中直接编写单测内容。 图片 在demo中,可以直接点击gitlab链接跳转到对应issue。 图片 这里拿一个简单的issue做演示: 图片 对应的原子单测。 复制 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(); }); }); 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 单测非常简单,虽然只有两句expect,但这两句是只为这个issue存在,强行cp。 issue唯一单测覆盖,保证0改动引发。 在业界一些优秀的开源框架也是有同样的issue即单测的案例,比如mobx。 (编辑:肇庆站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |