最近写了几个cli工具,奈何对单元测试还不是特别熟悉。尤其是对这种bin文件的单测,更是没有丝毫接触过。
昨天抽了一些时间去了解了一下,故作此记录。
怎么测
首先要知道bin文件本身只是一个可执行的node文件。想运行它,我们可以使用node的child_process
模块开一个新线程去执行
这里我们可以借助execa
,execa
是对child_process
的一层封装。相较于child_process
它有一些自身的优势 :
- 更为简单的API
- 跨平台
- 更好的错误处理
- 自动清理僵尸进程
示例
比如这么一个bin文件
#!/usr/bin/env node
import { cli } from 'cleye';
import startExecution, { ProfileOptions } from './';
import packJson from '../package.json';
const argv = cli({
name: 'gdal2tiles-node',
version: packJson.version,
description: 'gdal2tiles-node',
flags: {
zoom: {
type: String,
alias: 'z',
},
profile: {
type: String,
alias: 'p',
},
input: {
type: String,
alias: 'i',
},
output: {
type: String,
alias: 'o',
}
}
});
const {
input,
output,
zoom,
profile
} = argv.flags;
if (input && output) {
startExecution({
input,
output,
zoom,
profile: profile as ProfileOptions
});
}
else {
console.info('请输入输入和输出路径');
}
这里,我们就简单测试一下当前文件的参数传递
import { execa } from 'execa';
import path from 'path';
describe('gdal2tiles-node', () => {
it('no parameters', async () => {
const { stdout } = await execa('ts-node', [`${path.join(__dirname, '../cli.ts')}`]);
expect(stdout).toBe('请输入输入和输出路径');
});
it('no input parameter', async () => {
const { stdout } = await execa('ts-node', [`${path.join(__dirname, '../cli.ts')}`,"-i='./'"]);
expect(stdout).toBe('请输入输入和输出路径');
});
it('no out parameter', async () => {
const { stdout } = await execa('ts-node', [`${path.join(__dirname, '../cli.ts')}`,"-o='./'"]);
expect(stdout).toBe('请输入输入和输出路径');
});
});
简单解释一下:
- 因为是ts文件,故这个脚本我们是需要借助一下
ts-node
去处理 - execa的api是基于promise的,故可以使用
await
语法 - stdout,是一个字符串类型的返回值,它表示的是文件的标准输出内容。eg:bin文件中的一些log、info
拓展知识
怎么理解标准流
在计算机中,标准流是指与操作系统、应用程序或其他进程进行通信的标准输入、标准输出和标准错误输出。它们分别对应着三种文件描述符
- 标准输入 stdin :文件描述符为0,用于从键盘或者其他输入设备读取数据
- 标准输出 stdout: 文件描述符为1,用于向其屏幕或者其他输出设备输出数据
- 标准错误输出 stderr: 文件描述符为2,用于向其他屏幕或其他输出设备输出错误信息
标准流是一种非常重要的输入输出机制,它使得各种程序之间可以通过标准输入输出进行通信,并且可以重定向标准输入输出来控制程序行为。
参考
原文链接:https://juejin.cn/post/7225596319447629883 作者:小宫同学