1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

deno test で `Test case is leaking async ops.` が出た時の対処法

Last updated at Posted at 2022-04-03

deno testコマンドには、test sanitizerという機能があります。この機能は

  • Promiseの待ち忘れ
  • ファイルやWebSocketの閉じ忘れ

などをチェックしてくれる機能です。
このチェックに引っかかると「Test case is leaking async ops.」や「Test case is leaking 1 resource:」「Test case attempted to exit with exit code: 0」と怒られます。

それぞれのエラーの意味

  • 「Test case is leaking async ops.」:Promiseを全てawaitしていない(テスト終了時にresolveされていないPromiseが残っている)
  • 「Test case is leaking 1 resource」:ファイルやWebSocketなど、closeしなければいけないものをcloseしていない
  • 「Test case attempted to exit with exit code: 0」:テスト中にDeno.exit()が呼び出されたため、後続のDeno.test()が実行されない

「Test case is leaking async ops.」の対処法

「Test case is leaking async ops.」はPromiseの待ち忘れがあるときに発生します。

test.ts
import { delay } from "https://deno.land/std@0.133.0/async/mod.ts";

Deno.test(function test() {
  /* await */ delay(100); // ここでawait していないためエラー
});
> deno test ./test.ts
running 1 test from file:///C:/Users/azusa/work/deno/test/test.ts
test test ... FAILED (20ms)

failures:

test
Test case is leaking async ops.

- 1 async operation to sleep for a duration was started in this test, but never completed. This is often caus
ed by not cancelling a `setTimeout` or `setInterval` call.

To get more details where ops were leaked, run again with --trace-ops flag.

failures:

        test

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out (60ms)

error: Test failed

例は単純なコードでしたが、大きいコードベースではどのPromiseに対してawaitを忘れているのかが一目では分からないことがあります。
そういう時は --trace-opsフラグを付けて再実行することで、どのPromiseを待ち忘れたかを知ることができます。

> deno test --trace-ops ./test.ts
running 1 test from file:///C:/Users/azusa/work/deno/test/test.ts
test test ... FAILED (30ms)

failures:

test
Test case is leaking async ops.

- 1 async operation to sleep for a duration was started in this test, but never completed. This is often caus
ed by not cancelling a `setTimeout` or `setInterval` call. The operation was started here:
    at Object.opAsync (deno:core/01_core.js:164:42)
    at runAfterTimeout (deno:ext/web/02_timers.js:215:31)
    at initializeTimer (deno:ext/web/02_timers.js:181:5)
    at setTimeout (deno:ext/web/02_timers.js:318:12)
    at https://deno.land/std@0.133.0/async/delay.ts:23:15
    at new Promise (<anonymous>)
    at delay (https://deno.land/std@0.133.0/async/delay.ts:14:10)
    at test (file:///C:/Users/azusa/work/deno/test/test.ts:4:3)
    at testStepSanitizer (deno:runtime/js/40_testing.js:444:13)
    at asyncOpSanitizer (deno:runtime/js/40_testing.js:145:15)

failures:

        test

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out (215ms)

error: Test failed

見るべき場所はスタックトレースで、下から2行目にあるfile:///始まりのパスがあなたのコードに関する部分です。ここに表示されているファイル名と行数を辿ると、awaitしていないPromiseがあります。

--trace-opsオプションを付けると詳しいエラーが表示される分、実行速度が遅くなるようです。CIなどでは--trace-opsオプションを付けずに実行して置き、エラーが出た場合に限り--trace-opsオプションを付けるとよいでしょう。

修正できない場合の回避策

このエラーが出る原因が別ライブラリにあり、修正が難しい場合、Deno.test()にオプションを渡してこのエラーを無視することができます。

Deno.test({
  name: "test",
  fn() {
    Deno.open("./a.ts");
  },
  // sanitizeOps: false, // 「leaking async ops」 を無視
  // sanitizeResources: false, // 「leaking resource」を無視
  // sanitizeExit: false, // 「exit with exit code: 0」を無視
});

sanitizeOps/sanitizeResources/sanitizeExitそれぞれのオプションをfalseに設定すると、test sanitizerが無効になります。

ただしsanitizeExitfalseにしてエラーを無視すると、後続のテストが実行されなくなるので注意が必要です。

Deno.test({
  name: "test",
  fn() {
    Deno.exit();
  },
  sanitizeExit: false,
});

Deno.test(function name() {
  // このテストは実行されない(上のDeno.exit()で強制終了されるため)
  console.log("aaa");
});

まとめ

  • deno testコマンドで発生する「Test case is leaking async ops.」や「Test case is leaking 1 resource:」「Test case attempted to exit with exit code: 0」エラーはtest sanitizerが検出したもの
  • Promiseのawait忘れの該当箇所を発見するには--trace-opsフラグを使う
  • これらのエラーを無視するにはオプションのsanitizeOps/sanitizeResources/sanitizeExitfalseに設定する
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?