当前位置: 首页 > 科技观察

优秀工程实践-前端高质量单测

时间:2023-03-21 10:56:25 科技观察

作者|范哲(六瓶)单测高就等于质量高?笔者负责的npm包是ICBU信天翁低代码平台渲染引擎。基于该引擎开发了160+应用,600+页面,内网npm日下载量1K+。经过不懈的努力(CV),终于把单考提高到了95%。不过,虽然在覆盖范围内获得了一些数据变化,但是作为开发者,想要的不是完美的数据,而是真正的完美(无BUG)。作为一个被频繁引用的底层库,更改一行代码可能会影响用户意想不到的错误。高单测覆盖率避免不了变化,小的变化可能导致线上大问题。写单测issue=singletest每个issue都有自己命中注定的单测。在我们的项目中,问题用于管理用户需求。用户每次发现问题,都可以到我们指定的仓库提出问题。新增问题触发机器人在钉钉群中对应编辑,修复后机器人通知创建者。在软件工程中,单元测试的描述是“对每个单元进行一次测试,以确保每个模块都能正常工作”。在我们的线路覆盖率和分支覆盖率都很高的情况下,需要一种新的机制来保证模块更加稳定。除了那些框架还没有探索的业务场景,如何保证当前用户一定没有问题?那么就有一个问题,就是单测。在目前的issue运行机制下,保证每一方都有对应的issue。将脚本tnpmruncreate-issue添加到存储库。//package.json"scripts":{"create-issue":"node./script/issue_dev/createIssueTem.js",}//createIssueTem.js/***快速创建问题示例*/constpath=require('path');constexecSync=require('child_process').execSync;constargs=process.argv.slice(2);constissueID=args[0];if(!issueID){console.error('需要输入issueid才能运行');process.exit();}constdemoTarget=path.resolve(__dirname,`../../demo/issue_${issueID}`);constdemoSrc=path.resolve(__dirname,`../template/demo/base.md`);consttestTarget=path.resolve(__dirname,`../../test/issues-cov/${issueID}`);consttestSrc=path.resolve(__dirname,`../template/test/*`);constspecTarget=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}成功`);deletethecorrespondingdemobeforepublishing//prebuild//deletethedemoconstoftheissuebeforebuildingfs=require('fs');constpath=require('path');constENV=process.env.BUILD_ENV=='云';functionremoveDir(dir){letfiles=fs.readdirSync(dir);for(vari=0;i{if(err){console.log(err);}path.forEach((pathItem)=>{if(pathItem.includes('issue')&&ENV){removeDir(`./demo/${pathItem}`);console.log(`remove${pathItem}`);}});});运行时帮助我们tnpmruncreate-issue123456创建对应issue123456的单元测试+demo,复用相同的模板内容,可以在浏览器端看到demo,或者直接在vscode中编写单元测试内容。在demo中可以直接点击gitlab链接跳转到对应的issue。这里有一个简单的问题作为演示:对应的原子单测。describe('116193',()=>{it('应该工作',async()=>{constwrapper=mount();awaitsleep(10);wrapper.mount();expect(Object.keys(A)).toMatchSnapshot();expect(A.hasApplied).toBeDefined();returnwrapper.unmount();});});单机测试很简单,虽然只有两个expect,但是这两个只是为了这个issue而存在,forcecp。Issue是唯一确保触发0变化的单一测试覆盖率。业界一些优秀的开源框架也有同样的问题,就是测试用例单一,比如mobx。单测=文档原子类单测可以很大程度保证代码的稳定性,组件类可以描述开发者期望的用法。单个测试是一个文档。闭环沉淀反馈另外,issue的Milestone代表对应的npm版本://changelog#1.24.01。[FEAT]列表过滤提供了一种类似表单的验证方式#115827(被测试覆盖)2.[FEAT]built-inmodelAttributesshouldnotbeenumerable#116193(被测试覆盖)3.[FEAT]希望提供ref注释以方便平台端的区分#1163644。[Bug]在watch的常规模式下,调用silentvalidate会导致autoValidate失败#116242(coverbytest)问题的最佳归宿是coverbytest。钉钉->issue->npmchangelog一一对应,让每一个单测都可以追溯。作者负责的框架实现了一年,再来回顾一下。重新设计架构是否可以完美解决当前的这些问题,值得思考。这些问题和单元测试都是足迹,现在我们已经积累了170+个单元测试,其中60+个问题是原子单元测试。0BUG无法保证。但可以预见的是,用户可以放心使用,不会有任何变化。单体测试是质量的守门人,帮助框架满足用户期望,一步步向前。最后,编写单元测试的最佳时间是在项目开始之前,其次是现在。

猜你喜欢