created: 2024-06-19T07:53:53.665Z

zx と node:test のおかげでちょっとしたスクリプトは nodejs/mjs で書くとラク

zx を使い始めたおかげでシェルスクリプトを書くことが減った。 だいたいのプロジェクトで nodejs はなんかしら使うので、mjs ファイルに zx を import して使うことが多い。

nodejs にビルトインのテストツールが入っていて、完全な TDD をするというよりもちょっとした動作確認にこれがけっこう便利なのでよくつかっている。

引数が 3 つ以上あったり、細かい文字列操作がしたいスクリプトは mjs で書くほうが楽だと思う。

--test オプションを用意する

zx.argv.test で処理を切り分けている。

import { argv } from "zx";

...(実装)

if (argv.test) {
  runTests();
} else {
  main(argv);
}

こんな実行でテストのみの実行になる

./cli.mjs --test

node:test がだいたいできる

jest でよく使うものはだいたいある。

引数エラーのテスト

たとえば ctx.mock.method(process, "exit") とかすればちょっと面倒だけどプロセスの異常終了時のテストができる。

import test, { describe } from "node:test";

function runTests() {
  describe("parseArgs", () => {
    test("--table option is mixed and recentDays is set", (ctx) => {
      // mock
      const { mock } = ctx.mock.method(process, "exit");
      mock.mockImplementationOnce(() => {});
      // exec
      parseArgs({ ... });
      // verify
      assert.match(
        mock.calls[0].arguments[0],
        /Validation error: --recent-days is not support log and non-log tables are mixed/
      );
    });
  });
}

zod で引数をチェックする

zod はだいたいのプロジェクトでつかっているのでヌルッと import できる。

import { z } from "zod";
import { fromError } from "zod-validation-error";

...

  const result = argSchema.safeParse(...);
  if (!result.success) {
    console.log(chalk.red(fromError(result.error).toString()));
    process.exit(1);
  }

zod のエラーメッセージそのままだとコマンドラインツール的には読みにくい。引数エラーは zod-validation-error というので文字列に変換すると完璧ではないけどだいぶ読みやすくなってよかった。

こんなかんじ

Validation error: Expected string, received boolean at "loginPath"

その他

shebang を工夫したら typescript/ts-node で実行できないかなと思っている。 しかしチームで作ってるやつだと ts-node をグローバルに入れてもらうのは大変そうなのでこれはやってない。

刑務所の経済学
[ad] 刑務所の経済学
中島 隆信 (単行本(ソフトカバー))