【源码学习】omit.js源码及测试用例调试

256 阅读7分钟

前言

加入源码共读以后,这是我写的第二期活动了,测试用例和auto-attach调试确实没怎么了解过,结合了几篇同学的同期作业来参考,逐渐明白其中的用处,这确实是一种不错的学习方法,研究未知的知识点,积少成多,量变才能引发质变,接下来就开始这一期的学习。

一、项目主要结构

omit提供一个剔除对象中的属性的方法,从github下载下来,研究一下项目内部结构及源码

微信截图_20230315221425.png

  • src:主要的项目源码
  • tests:测试用例文件
  • .fatherrc.js: father库的配置文件,father是npm的包研发工具
  • package.json: 项目依赖文件

二、package.json

image.png

  1. assert

    assert断言工具,如果表达式判断为true则通过,如果为false,刚抛出error,使用场景:
    1.大型项目,众多函数调用情况下,判断某一个流程节点的值,是否正确,符合预期
    2.函数传参时候,判断参数情况

 部分API: 
 
  (1) assert(value[, message])**
  当 `value` 为 true 时,测试通过
  当 `value` 为 false 时,测试不通过通过,抛出带有 `message` 的错误
  (2) assert.equal(actual, expected[, message])
  当 `actual` == `expected` 为 true 时,测试通过
  当 `actual` == `expected` 为 false 时,测试不通过通过,抛出带有 `message` 的错误
  1. father

    对father的学习了解不多,希望以后能多用用进行深入研究。 father 是一款 NPM 包研发工具,能够帮助开发者更高效、高质量地研发 NPM 包、生成构建产物、再完成发布。它主要具备以下特性:

  • ⚔️ 双模式构建:  支持 Bundless 及 Bundle 两种构建模式,ESModule 及 CommonJS 产物使用 Bundless 模式,UMD 产物使用 Bundle 模式
  • 🎛 多构建核心:  Bundle 模式使用 Webpack 作为构建核心,Bundless 模式支持 esbuild、Babel 及 SWC 三种构建核心,可通过配置自由切换
  • 🔖 类型生成:  无论是源码构建还是依赖预打包,都支持为 TypeScript 模块生成 .d.ts 类型定义
  • 🚀 持久缓存:  所有产物类型均支持持久缓存,二次构建或增量构建只需『嗖』的一下
  • 🩺 项目体检:  对 NPM 包研发常见误区做检查,让每一次发布都更加稳健
  • 🏗 微生成器:  为项目追加生成常见的工程化能力,例如使用 jest 编写测试
  • 📦 依赖预打包:  开箱即用的依赖预打包能力,帮助 Node.js 框架/库提升稳定性、不受上游依赖更新影响(实验性)
  1. np

    一个更好用npm发布工具

 包含功能:
(1)交互式UI
(2)可通过生成单独配置文件.np-config.json进行配置

三、源码

//参数为目标对象、需要删除的对象key数组
function omit(obj, fields) {
  //使用Object.assign对目标对象进行浅拷贝
  const shallowCopy = Object.assign({}, obj);
  //遍历key数组
  for (let i = 0; i < fields.length; i += 1) {
  //拿到key数组中第一个key值
    const key = fields[i];
  //删除浅拷贝对象中的对应的属性
    delete shallowCopy[key];
  }
  //返回经过循环处理的浅拷贝对象
  return shallowCopy;
}
export default omit;

分析:
(1)这个比单独使用delete删除对象属性方便,单独使用delete会改变原对象,omit方法复制一个新对象进行操作并返回;
(2)Object.assign为浅拷贝,如果某个属性的值为对象,那拷贝的是该对象的引用。

四、调试

以前经常使用浏览器控制台console.log()进行调试,这次学习了大佬的vsCode调试方法,通过配置auto-attach在编辑器中调试。

  1. 配置auto-attach为【智能】模式 微信截图_20230316171814.png 微信截图_20230316171839.png

  2. 在js文件中设置好断点,通过终端node命令行执行js文件进行调试 微信截图_20230317001407.png

  3. 调试按钮说明:

 1.  继续(F5): 点击后代码会直接执行到下一个断点所在位置,如果没有下一个断点,则认为本次代码执行完成。

2.  单步跳过(F10):点击后会跳到当前代码下一行继续执行,不会进入到函数内部。

3.  单步调试(F11):点击后进入到当前函数的内部调试,比如在 `fn` 这一行中执行单步调试,会进入到 `fn` 函数内部进行调试。

4.  单步跳出(Shift + F11):点击后跳出当前调试的函数,与单步调试对应。

  1. 目前这样的调试方法只适用于js文件,很多使用框架的项目代码由于代码压缩,不能直接调试,需要通过相应的配置开启sourcemap,在浏览器环境例如chrome devtools中进行调试,调试的方法很多,掌握多种方法可以更好地提高效率。
  2. 通过这个断点调试,更直观地观察代码运行逻辑、变量以及调用堆栈,一方面有利于我们平时修改bug,另一方面也可以很好地帮助学习理解源码。

五、测试用例

  1. 项目目录下的tests/index.test.js文件为测试用例,之前没用过,查阅资料后有所了解,Jasmine 是一个简易的 JS 单元测试框架。Jasmine 不依赖于任何浏览器、DOM、或者是任何 JavaScript 而存在。它适用于所有网站、Node.js 项目,或者是任何能够在 JavaScript 上面运行的程序。 微信截图_20230317003924.png
  2. 这个测试用例使用assert模块从两个方面对omit进行测试:
(1)是否新生成了一个浅拷贝对象
(2)是否能够正确地删除传入的属性
  1. 使用Jest单元测试来重写测试用例
为什么使用Jest来重写呢
  • 速度快,使用简单和容易配置
  • 通过编写测试,让代码出现 bug 的概率更小
  • 有利于写出健壮性更好的代码,项目的可维护性增强
  • 好的测试,就具有文档解释的作用
  • 减少回归测试中的 bug
3.1 安装jest依赖
    npm i jest -D
3.2 添加jest.config.js配置文件
    npx jest --init
3.3 命令行进行配置项目选择
     √ Would you like to use Jest when running "test" script in "package.json"? ... yes
     √ Would you like to use Typescript for the configuration file? ... no
     √ Choose the test environment that will be used for testing » node
     √ Do you want Jest to add coverage reports? ... no
     √ Which provider should be used to instrument code for coverage? » v8
     √ Automatically clear mock calls, instances, contexts and results before every test? ... yes
3.4 根目录新建babel.config.js文件,写入以下配置:
 module.exports = {
     presets: [
         [
             '@babel/preset-env',
             {
                 targets: {
                     node: 'current', 
                 },
             },
         ],
     ],
 };
  
3.5 使用jest修改测试用例

import omit from '../src';
describe('omit', () => {
    it('should create a shallow copy', () => {
        const benjy = { name: 'Benjy' };
        const copy = omit(benjy, []);
        expect(copy).toEqual(benjy)  // expect()为期望测试方法,toEqual()为可测试对象类型值的方法
    });

    it('should drop fields which are passed in', () => {
        const benjy = { name: 'Benjy', age: 18 };
        const testObj1 = omit(benjy, ['age'])
        const tsetObj2 = omit(benjy, ['age', 'name'])
        expect(testObj1).toEqual({ name: 'Benjy' })
        expect(tsetObj2).toEqual({})
    });
});
3.6 执行npm run test,测试通过

微信截图_20230317124518.png

3.7 执行npm run coverage 查看测试覆盖率,同步生成coverage文件夹,里面的Icov-report中的html文件可以通过浏览器打开查看报告

微信截图_20230317124747.png

微信截图_20230317125252.png

关于jest单元测试的使用

除了提高项目代码健壮性,在维护老项目的时候也很有用处,比如需要修改某一部分代码,你不知道其中 的是否有复杂的关联关系,牵扯到其它组件或功能,但是加入了测试后,直接运行所有测试代码就可以知道是否影响其它的功能代码,如果之前老项目没有写单元或者集成测试,可以加入测试代码,便于更好地维护。

六、NPM发布

  1. github新建仓库远程推送本地项目,刚好加上上一期学习的两个npm包,可以实现自动提升版本、打 tag、生成 changelog ,规范commit提交等功能:
npm i git-cz -D      //规范commit提交
npm init release-it  //自动提升版本、打 tag、生成 changelog
npm i @release-it/conventional-changelog -D  //依赖
  1. 执行release
npm run release
  1. 登录npm,执行发布命令,发布成功
npm login
npm publish

微信截图_20230317195729.png 4. 删除npm包

npm unpublish <npm name> -force

七、总结

  • 下载Omit.js项目文件进行分析,对项目结构及依赖有了进一步的理解
  • 了解了一些新的npm包,assert断言工具,father包研发工具,np包发布工具,之前没用过,这次任务去拓展了解了一下,拓展了视野
  • omit.js源码并不复杂,通过浅拷贝和遍历来实现整个方法
  • 学习了node.js的调试方法
  • 了解了前端测试相关的知识,jest单元测试框架的优势
  • 复习上一期任务中的知识点,commit提交规范、release自动提升版本、npm发包等等