加入收藏 | 设为首页 | 会员中心 | 我要投稿 肇庆站长网 (https://www.0758zz.cn/)- 数据分析、分布式云、安全管理、云计算、物联设备!
当前位置: 首页 > 云计算 > 正文

卓越工程实践之—前端高质量单测

发布时间: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。

(编辑:肇庆站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读