QR Send

スマホとPCのChrome間で、URLやテキストをQRコード1回のペアリングで送り合える自作Chrome拡張。アカウント不要・無料。

使ってみる →

PlaywrightのテストでTypeScriptに最初につまずくところ:Cannot find module(TS2307)を順番に片づける

Selenium・自動化

テストのロジックより先に、importで詰まる

Playwright + TypeScriptで環境を作った直後、いきなり赤線に出会うことがあります。

import { test, expect } from '@playwright/test';
import { login } from '@/utils/auth';

エディタ上ではこう出ます。

Cannot find module '@/utils/auth' or its corresponding type declarations.ts(2307)

まだ1行もテストのロジックを書いていないのに、いきなりTS2307です。私も何度か踏みましたが、原因は毎回バラバラでした。パッケージが入っていないだけの時もあれば、型定義だけが足りない時、パスの設定がずれている時もあります。今回はこのTS2307を、原因の切り分け方の順番でまとめてみます。

まず疑うべきは「入っていない」だけ

一番多いのは、単純にパッケージ自体がインストールされていないケースです。npm installし忘れたまま、他の人が書いたテストをcloneして開いた時によく起きます。

npm ls @playwright/test

ここで(empty)not found系の表示が出たら、まずはインストールを確認しましょう。

npm install -D @playwright/test
npx playwright install

これで直ればラッキーです。瞬殺ですね。ただ、私がハマった時はここでは直りませんでした。ここからが本番です。

次に疑うべきは「型定義だけがない」パターン

パッケージ自体はあるのに、process.envpath.joinのようなNode.js標準の部分だけが赤線になることがあります。

const baseUrl = process.env.BASE_URL;
// Cannot find name 'process'. Do you need to install type definitions for node?

これは@types/nodeが入っていないのが原因であることが多いです。Playwright自体はテストを実行するための型定義を持っていますが、Node.jsの組み込みAPI(processfspathなど)の型はまた別で、@types/nodeを入れて初めて認識されます。

npm install -D @types/node

私のプロジェクトでは大体これでprocess周りの赤線は消えます。ただ、正直に言うと「Playwright公式のどのページに@types/nodeが必須と明記されているか」までは見つけられませんでした(私も探しましたが、公式のTypeScriptガイドには言及がありませんでした)。実務では入れておくと詰まりにくい、という経験則として書いています。

それでも消えない時は、パスエイリアスを疑う

ここまでやってもまだ@/utils/authのようなエイリアス付きのimportだけが赤線のままなら、疑うのはtsconfigのパス設定です。@/のようなエイリアスは標準機能ではなく、tsconfig.jsonで自分で定義する必要があります。

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  }
}

ここで注意したいのは、Playwrightのテストランナーがtsconfig.jsonの全部のオプションを見てくれるわけではない、という点です。公式ドキュメントには次のように書かれています。

Playwright only supports the following tsconfig options: allowJs, baseUrl, paths, references and extends

つまりpathsbaseUrl自体はPlaywrightが直接解釈してくれます。エディタ(tsc側)だけがエイリアスを解決できていて、実行時のPlaywrightが解決できていない、という食い違いは基本的には起きにくい作りです。

ただ、実際にはPlaywrightのバージョンによってエイリアス解決がうまくいかない不具合が過去に何度か報告されています。GitHubのIssueを見ると、あるバージョンでは動いていたパスエイリアスが別のバージョンで解決できなくなった、という報告もありました。バージョンごとに挙動が変わりうる部分なので、直らない時は一旦relativeパス(../utils/auth)に書き換えて動くかどうかを確認するのが早いです。動けば、原因はエイリアス解決側にあると切り分けられます。

// 動作確認用に一旦relativeに戻してみる
import { login } from '../../utils/auth';

3つの原因を順番に切り分ける

整理すると、TS2307に出会った時は次の順番で見ていくと早いです。

  1. パッケージ未インストール: npm ls <パッケージ名>で入っているか確認
  2. 型定義未インストール: Node標準APIなら@types/node、外部ライブラリなら@types/<ライブラリ名>が別途必要かを確認
  3. パス設定のずれ: tsconfig.jsonのbaseUrlpathsが合っているか、一旦relativeパスに書き換えて解決するか確認

この順番で見ていくと「型定義は入っているのにパスだけ直せば済む話」を、パッケージの再インストールから始めて無駄に時間を使う、みたいな遠回りをしなくて済みます。

そもそもJavaScriptで書いていた頃は起きなかった問題

Selenium + Rubyで書いていた頃は、こういう「型の解決で赤線が出る」という悩み自体がありませんでした。実行時にエラーが出て初めて気付く世界だったからです。TypeScriptに移行してからは、実行前にエディタが教えてくれる代わりに、こうした環境まわりのつまずきが増えた実感があります。私自身のSeleniumからPlaywright + TypeScriptへの移行で感じた変化はこちらの記事にまとめているので、移行を検討している方は合わせて読んでみてください。

また、こうした環境まわりの問題はローカルでは再現するのにCI環境だけ通る・落ちるという形で顔を出すこともあります。node_modulesのキャッシュの有無やtsconfigの読み込まれ方の違いが原因になっていることがあるので、CI側の設定に不安がある方はGitHub Actions入門の記事も参考にしてみてください。

原因不明のimportエラーは、テストを絞って再現させる

プロジェクトが大きくなってくると、どのテストファイルでエラーが出ているのか分かりにくくなることがあります。そんな時は特定のテストファイルだけに絞って実行すると、切り分けが早くなります。

npx playwright test --grep "login"

--grepを使ったテストの絞り込み方はCLIオプションの記事で詳しく書いています。エラーが出ているテストだけを繰り返し実行しながらtsconfigを直していけるので、これ、意外と使えます。

正直に言うと、環境依存でハマることはまだあります

ここまで書いた3ステップで大体のTS2307は片づきますが、モノレポ構成でtsconfigが複数階層になっている場合や、tsconfigをコマンドラインで明示的に指定している場合は、想定と違うtsconfigが読み込まれてこの切り分けだけでは足りないこともあります(このあたりは私も毎回完全に理解できているわけではなく、詰まるたびに公式ドキュメントとGitHub Issueを読み直しています)。パッケージ・型定義・パス設定の3つで直らない時は、そもそもどのtsconfig.jsonが読み込まれているのかを疑ってみてください。

まとめ

Playwright + TypeScriptの最初のつまずきは、テストのロジックよりも前にimportの赤線であることが多いです。パッケージが入っているか、型定義が入っているか、パス設定が合っているか。この順番で見ていけば、大抵は瞬殺で片づきます。同じところでハマっている方がいたら、コメントで詰まりポイントを教えてもらえると嬉しいです。

コメント

タイトルとURLをコピーしました