用TDD的方式写一个package(上)

334 阅读3分钟

最近看了很多有关npm包管理的文章,于是就试着自己搭建一个utils库来理一下搭建过程中可能遇到的问题。 以此来检验自己是否真的掌握 同时也浅尝一下TDD开发的体验

目标

  1. 发布到npm仓库,可通过pnpm install xxxx下载到本地使用
  2. 每个文件必须包含测试文件,保证代码质量
  3. 可通过import以及script标签来引用

开发环境

node: v18.2.0

pnpm: 8.1.0

vite: 0.29.8

初始化

  1. npm init 然后一路enter就可以了
  2. 新建src目录mkdir src,用于存放代码 cd src && touch index.ts index.ts用作对外输出的一个根文件,也就是所有的import都会由index.ts来完成
  3. 安装eslint npm init @eslint/config 按照eslint官网直接使用命令来安装 可省去很多复杂的百度环节 一路enter就行
  4. 手动安装所需的包文件pnpm install typescript vite vitest vite-plugin-dts -D

添加一些配置文件

  1. vite.config.ts
import { defineConfig } from 'vite'
import { resolve } from 'path'
import dts from 'vite-plugin-dts'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: 'src/index.ts',
      name: 'js-tools',
      formats: ['es', 'umd']
    },
    sourcemap: true,
    target: 'modules',
    outDir: 'dist',
    minify: false,
    rollupOptions: {
      external: ['lodash', 'lodash-es'],
    }
  },
  plugins: [dts()],
  resolve: {
  },
})
  1. tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "useDefineForClassFields": true,
    "lib": [
      "DOM",
      "DOM.Iterable",
      "ESNext"
    ],
    "allowJs": false,
    "skipLibCheck": true,
    "declaration": true,
    "declarationDir": "./dist/types",
    "emitDeclarationOnly": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": false,
    "noEmit": false,
    "baseUrl": ".",
    "outDir": "./dist",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ]
}
  1. .npmrc
registry=https://registry.npmmirror.com

还有一些例如.editorconfig .eslint等配置文件就不一一列举了 根据自己的习惯去配置 husky comminlint stylelint等等,网上有很多这样的文章

第一个测试文件

为了让自己更好的清楚写的函数具有什么功能,我们先从测试文件写起吧。那我们就先来写一个add函数

函数描述:把所有该函数的参数进行累加,并返回累加的结果

看上去很简单,把函数的参数作为一个数组累加返回就行了,我们先用伪代码来试着写一下测试用例吧

  1. 两位数: add(2,3).toBe(5)
  2. 三位数:add(2,3,1).toBe(6)
  3. 一位数:add(4).toBe(4)
  4. 没有参数:add().toBe(0)

感觉还少了点什么 对了,还有参数的类型判断 那就加上 (其实ts已经帮我们对参数做了校验了,不过为了测试,直接改成了any[])

  1. 参数类型错误: judge(arg).notToNumber.throwError('参数类型必须都是number')

把这些伪代码还原一下吧:

add.test.ts

import { describe, expect, test } from 'vitest'
import { addNumber } from './add'

describe('加法测试', () => {
  test('加法测试三位数', () => {
    expect(addNumber(1, 2, 3)).toBe(6)
  })
  test('加法测试一位数', () => {
    expect(addNumber(98)).toBe(98)
  })
  test('加法测试0位数', () => {
    expect(addNumber()).toBe(0)
  })
  test('加法测试参数不是number', () => {
    expect(() => addNumber(3, false)).toThrowError('参数不能有非数字类型')
  })
})

OK 我们可以开始写代码了,现在是不是思路很清晰了

add.ts

/**
 * @description 数字累加
 * @param args number[] or arrayLike
 * @returns number
 */

const addNumber = (...args: any[]) => {

  if (args.some((v, i) => typeof v !== 'number')) {
    throw new Error('参数不能有非数字类型')
  } else {
    return args.reduce((pre, curr) => pre + curr, 0)
  }
}
export { addNumber }

故意多加一个1 看看效果 果然测试用例错误 完美

到此,已经完成了一个add函数的源码和测试用例编写了 如果后面再往这个add函数添加逻辑 看着这些绿色的通过标志,是不是更加放心了呢

接下来让我们一起把这个代码发布上去吧。