ふくふくHukuhuku LLC
EP.73Toolbox 12分公開:

Deslop 0.4.6でAIコードを検収 同じ関数を繰り返すテストと検査の限界を試す

Deslopの新ルールを日本語の架空TypeScriptコードで検証。同じ関数を繰り返すassertionの検出、意図した反復への指摘、lintを通過する業務計算ミスまで14例と教材で紹介します。

#Deslop#Oxlint#TypeScript#AIコードレビュー
執筆 / 監修
松尾 亮合同会社ふくふく 代表社員

データ基盤・データパイプライン構築 / BI / 生成 AI 活用支援を専門とするエンジニア (28 年)。 本記事は AI 利用ポリシーに基づき、生成 AI の補助で執筆 → 人間が監修・編集して公開しています。

プロフィール詳細
シェア

AIにテストコードを書いてもらうと、行数は増えているのに、同じ関数を何度も実行して別々の項目を確かめる形になることがあります。処理が純粋な計算なら余分な実行で済んでも、採番や状態の更新が入ると、何を検証しているのかが変わります。コードレビューで見落としやすい、こうした書き方を機械的に拾う道具がDeslopです。

ここで扱うのはmaharshi365/deslop、npmパッケージ名はai-deslopです。同名の別のコード整理ツールとは区別してください。2026年10月14日朝、v0.4.6を使って、日本語の変数名や文面を含む14件の架空TypeScriptコードを試しました。今回追加されたルールは反復呼び出しを見つけましたが、意図した反復にも反応し、業務仕様の誤りは通過しました。使いどころは、レビューする箇所を絞ることにあります。

ATTENTION 検査を通すためにテストの意味を変えない

同じ関数を1回にまとめると、採番や状態遷移を確かめるテストが壊れる場合があります。新ルールに自動修正機能はありません。指摘された理由とテストの目的を確認し、修正後もテストを実行してください。

v0.4.6で増えたのは隣り合うassertionの検査

v0.4.6はnpmの公開記録では2026年10月14日2時49分に配布されました。時刻は日本時間です。新しいのはno-repeated-expect-callというルールで、同じ関数呼び出しを繰り返す隣接したassertionを検出します。assertionとは、実行結果が期待どおりかを確かめる記述です。

追加コミットとルール本体では、テスト用のファイル名・フォルダを対象に、隣り合う文のexpect(関数呼び出し)を比べています。ソース文字列が同じか、空白や一部の末尾カンマを除いたトークン列が同じなら指摘します。異なる書き方の処理が意味的に等しいかを推論する仕組みではありません。

DeslopはOxlintに追加するJavaScriptプラグインです。Oxlintは、コードを実行せずに構文や規則を検査するlintツール。Deslopはその上に、二重の型アサーション、固定文字列の部分一致だけのテスト、重複した定義などの独自ルールを足します。人が書いたコードにも同じ条件で反応し、LLMやAPIキーは必要ありません。

まず3ルールに絞って導入する

公式READMEは、Bun・Deno・Node.jsのOxlintプラグイン実行環境を案内しています。今回はNode.jsで動かしました。Deslopの本体はREADMEとnpmでMITライセンスと表示され、利用料金やAI推論の従量課金はありません。汎用ルールの一部はanti-slopから取り込まれています。

組み合わせたOxlint 1.82.0には、macOS・Windows・Linuxなどの環境別配布があります。npmのNode要件は^20.19.0 || >=22.12.0です。ただし、後述の教材はTypeScriptをNodeで直接実行するため、Node 22.18以降の22系または24系を使ってください。実測はmacOS 27.0、Apple silicon、Node 23.11.0、npm 10.9.2です。画面ではなくターミナルで使い、診断文は英語でした。

新しい空フォルダで、検証した版を固定して導入します。Deslopが依存する@oxlint/pluginsは1.82.0なので、Oxlint本体も同じ版にそろえました。インストールにはネット接続が必要ですが、以後の今回の検査で外部AIへの問い合わせは行いません。

Shell
npm init -ynpm install --save-dev --save-exact ai-deslop@0.4.6 oxlint@1.82.0 --ignore-scripts --no-audit --no-fund

設定ファイル.oxlintrc.jsonでは、まず次の3ルールを指定できます。既存プロジェクトに入れる場合は、今の設定に必要な項目を足してください。通常のlintや型検査を外す必要はありません。

JSON
{  "jsPlugins": [    "ai-deslop"  ],  "rules": {    "deslop/no-repeated-expect-call": "error",    "deslop/no-chained-type-assertions": "error",    "deslop/no-poor-substring-tests": "error"  }}

公式のrecommended設定には、今回の3つ以外にunknownを引数に使う記述やモジュールのmockなどを制限するルールもあります。また配布版の設定は型を参照する検査を有効にするため、そちらを使う場合は型を参照する検査の公式手順に従い、oxlint-tsgolintなどの準備が別途必要です。まずはチームが採用したい規則を選びます。OxlintのJSプラグイン機能自体もalpha扱いなので、版を固定して更新時に検査してください。

同じ請求書を2回作るコードは見つかった

最初の架空例は、請求書を作る関数の返り値を2つのassertionで確かめるコードです。実際の請求処理や外部APIはなく、関数は商品名と金額を持つオブジェクトを返すだけです。

教材の01-repeated-before.test.ts
TypeScript
function 請求書を作る(商品名: string) {  return { 商品名, 金額: 1200 };}expect(請求書を作る("月次レポート")).toHaveProperty("金額");expect(請求書を作る("月次レポート")).toEqual({ 商品名: "月次レポート", 金額: 1200 });

このファイルを検査すると、2つ目の呼び出しにdeslop(no-repeated-expect-call)が1件出て、終了コードは1になりました。診断文は「Call once and reuse the result across assertions.」。この例では、同じ1件の請求書を確かめたいので、結果を変数に保存するのが自然です。

関数の定義は同じ。教材02では結果の受け取り方を変更した
TypeScript
const 請求書 = 請求書を作る("月次レポート");expect(請求書).toHaveProperty("金額");expect(請求書).toEqual({ 商品名: "月次レポート", 金額: 1200 });

修正後は3ルールの診断が0件、終了コード0になりました。教材用の最小assertionでコードを実行した結果も、修正前・修正後とも成功しています。これは今回の架空例で意味を保てたという確認であり、どんな関数も1回にまとめてよいという意味ではありません。

意図した2回の処理までまとめると壊れる

反復呼び出しには、必要なものもあります。次は、呼ぶたびに番号が1つ進むかを確かめる例です。2回呼ぶこと自体が、テストの目的です。

教材04は意図的な反復。実行は成功するがlintは1件指摘した
TypeScript
let 現在番号 = 0;function 次の番号() { return ++現在番号; }expect(次の番号()).toBe(1);expect(次の番号()).toBe(2);

この例も新ルールに指摘されました。ところが、呼び出しを1回に減らして同じ結果を再利用すると、2つ目のassertionは「1と2が等しい」と要求することになり、実行が失敗しました。lintだけは通過します。指摘をすべて不具合と扱い、機械的に修正する運用が合わない理由です。

今回の修正例では、一回目 = 次の番号()、二回目 = 次の番号()と別々に呼んで保存し、それぞれ1と2を期待しました。この形なら処理の回数を維持し、lintと教材の実行の両方が通りました。実務では、テストの意図をコメントに残して、その箇所だけルールを抑制する判断もあり得ます。

同じ呼び出しを置いた条件v0.4.6の今回の結果
.test.ts内でassertionが隣接1件指摘
途中にconsole.logの文を1つ追加指摘なし
同じ内容を通常の.tsというファイル名に置く指摘なし
独自に定義した同名のexpect関数を使う指摘なし

別の文を挟むと対象から外れた点も、運用上の限界です。コード全体の重複呼び出しを網羅する検査ではなく、テストファイルの特定の並びを拾います。表の通過例は、警告を消すための書き換え方ではありません。レビュー時には関数の副作用と呼び出し回数を、人が確認する必要があります。

型を無理に通す記述と弱いテストも確認した

既存ルールも2つ試しました。no-chained-type-assertionsは、入力 as unknown as 請求書のように、型を2段階で強制的に扱い直す記述を検出します。架空の入力が文字列の"1200"なのに、請求書の金額は数値だと宣言した例では、lintに1件の指摘が出ました。実行しても文字列は数値にならず、期待値1200との比較は失敗しました。

固定した教材入力に対し、金額をNumber(入力.金額)で変換して型を付けた例では、診断と実行失敗がなくなりました。ただし外部入力を扱う実装では、空文字、数値に変換できない値、負数、許容範囲などを仕様に沿って検証する必要があります。二重のasを消すだけで入力検証が完成するわけではありません。

no-poor-substring-testsには、固定文字列「受付完了:注文A-001」の中に「受付完了」があるかだけを調べる例を渡しました。これは1件指摘されました。そこで、注文番号を受け取る関数の返り値を期待する全文と比較する例に替えると、指摘がなくなり、教材の実行も成功しました。少なくとも、単にその場に書いた文字列を確認する状態から、関数の出力を確認する形へ変わります。

一方、「本体価格に100円を加える」という架空仕様を、誤って50円加算にした関数は3ルールを通過しました。1200円を入力して1300円を期待するassertionは失敗し、100円加算へ直すと成功しました。lintは特定の書き方を検査し、業務上の期待値はテストで確かめる。この2つを一緒に運用する必要があります。

AIへの修正指示にもテストの目的を含める

最初の導入先は、AIが追加したテストと、その近くの実装が分かりやすいでしょう。レビュー時にルール名と該当箇所を返し、何を守って修正するかを併せて指示します。自動でファイルを直す前に、指摘だけを出して、意図した反復やチーム固有の書き方に過剰に反応していないかを見ると判断しやすくなります。

指摘を受けたコードの修正を依頼する例
Deslopの指摘箇所を確認してください。まず、このテストで同じ関数を複数回呼ぶ理由を説明してください。採番や状態の変化を確認する意図があれば、呼び出し回数と期待値を維持してください。同じ1回の結果を確認したい場合だけ変数へ保存します。assertionの削除、無関係な文の挿入、ファイル名の変更で指摘を回避しないでください。修正後はlintとテストを実行し、それぞれの結果を示してください。

今回の3ルールは、AIが書いたコードの検収に追加しやすい範囲でした。既存のテスト、型検査、レビューを維持したまま、同じミスを繰り返し指摘する負担を減らす用途で試すとよいでしょう。速度比較や一般的な検出率は測っていないため、14例の結果を全プロジェクトの品質改善率には置き換えません。

14件の架空例を自分の環境で再現する

架空TypeScriptコードと実測ログをダウンロードする。ZIPには14件のコード、固定版の依存情報、実行スクリプト、期待表と今回の観測結果を入れました。モデルやnode_modulesは含みません。新しいフォルダへ展開してから、次を実行します。

Shell
npm ci --ignore-scripts --no-audit --no-fundnode run_lab.mjs observed-new.jsonnode verify_saved_results.mjs observed-new.json

スクリプトは教材の14ファイルを個別に検査し、実行します。既存の業務コードは読みません。出力ファイルがすでにある場合は停止するので、再実行時は別の出力名を指定してください。今回のMacではnpm依存のファイル合計が約28.7MBでした。初回の取得後、今回の検査・実行にモデルのダウンロードはありません。

結果には、実際のDeslop診断と、教材用の最小assertionによる実行結果を分けて保存しています。後者はVitestやJestの動作検証ではありません。14件のうち4件でlintが指摘し、意図的に誤りを含めた3件は実行が失敗しました。この失敗も含めて期待表と一致すると、検算はPASS: 14 cases, 42 outcome checksになります。

保存済みの結果だけを見る場合は、npmの導入をせず、node verify_saved_results.mjs observed.jsonで検算できます。自分のコードへ広げる前に、指摘を受ける例、必要な処理なのに指摘される例、通過しても実行に失敗する例を見ておくと、この道具に任せる範囲を決めやすくなります。

よくある質問

DeslopにAIモデルやAPIキーは必要ですか?
今回扱うai-deslopはOxlint用の静的検査プラグインで、LLMやAPIキーは不要です。npm依存の初回導入にはネット接続が必要ですが、今回の架空コードの検査で外部AIへの問い合わせは行いませんでした。
指摘されたコードは自動で修正できますか?
v0.4.6のno-repeated-expect-callには自動修正機能がありません。採番などで複数回の呼び出しが必要なテストも指摘されたため、目的を確認して修正し、lintとテストの両方を実行してください。
lintを通過すればAIが書いたコードは正しいと判断できますか?
今回有効にした3ルールでは、100円加算すべき処理を50円加算にした架空コードが通過しました。計算結果のassertionは失敗したため、既存のテスト・型検査・コードレビューと併用する必要があります。
シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp