🧊

TypeScriptのテストファイルの読み方

OXCみたいなTypeScriptのコードを扱うツールを作ってると、TS(Compiler)のシンタックスエラーを同じように検出したくなる。

そのためのテスト用fixtureとして、TypeScriptリポジトリにあるテストファイルたちを参照してる。 OXCの場合、just submodulesってコマンドをプロジェクトルートで叩くと、tasks/coverage配下にクローンされてくるようになってる。

ただ、その使われ方を見てると少しクセがありそうだったので、それをまとめておく。

(DeepWikiがこういうところまでいい感じにまとめてくれたらよかったのに)

testsディレクトリ

TypeScript/tests at main · microsoft/TypeScript https://github.com/microsoft/TypeScript/tree/main/tests

このtestsディレクトリ配下がそれで、

  • baselines
  • cases
  • lib

という3つのディレクトリに分かれてる。

で、ユースケースを見るに、

  • cases/compiler
  • cases/conformance

というあたりにあるファイルたちを、いわゆるfixtureとして使うことが多いらしい。

compilerが基本となるケースで、conformanceは補足としていろんなバリエーションがカバーされてるイメージ。

@コメント

本題。

ここにあるテストファイルをいろいろ眺めてると、ただの.tsのコードって感じってのもあれば、@からはじまるコメントがいっぱい書かれてるのもある。

たとえば、compiler/import_reference-to-type-alias.tsの場合。

// @Filename: file1.ts
export module App {
    export module Services {
        export class UserServices {
            public getUserName(): string {
                return "Bill Gates";
            }
        }
    }
}

// @Filename: file2.ts
// @module: amd
import appJs = require("file1");
import Services = appJs.App.Services;
var x = new Services.UserServices().getUserName();

この@Filenameは、どうやらファイルが分割される想定を表す特別な区切りらしい。 (ちなみに@Filenameだったり@filenameだったり@FileNameだったり、表記は揺れまくってた)

つまり、このimport_reference-to-type-alias.tsは、単一の.tsファイルにはなってるけど、実際はただのテスト定義ファイルで、本当にテストしたいのは、file1.tsfile2.tsをあわせて読み込んだ場合・・・みたいな。

なので、雑に単一の.tsとしてパースしてしまうと、エラーになるべきがならなかったりするので注意しないといけない。

それ以外の@moduleなどは、お察しの通りでcompilerOptionsになってる。

  • @jsx
  • @strictNullChecks
  • @allowJs
  • @target
  • etc…

ということが、CONTRIBUTING.mdにはうっすら書かれてたけど、実物を見るまで把握できなかったので調べてみたという経緯。

TypeScript/CONTRIBUTING.md at main · microsoft/TypeScript https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md#adding-a-test

あと、これを調べてて気付いたけど、TSにはPlaygroundとは別に、Bug Workbenchってのもあるらしい。

TypeScript: Bug Workbench https://www.typescriptlang.org/dev/bug-workbench/

そしてこれの右パネルのDocsタブを見ると、なんとこの記事に書いてあることが全部書いてあったというオチ・・・!

baselines/referenceディレクトリ

あとは、特定のテストケースにおいて、TSCがエラーを出力する場合に、どういうエラーになる?というのが定義されてるのがココ。(エラー以外にも、JSにコンパイルした結果や、型、シンボルなんかも置いてある)

このディレクトリを見て、cases/compiler配下のテスト名と同じ名前で.errors.txtが置いてあるかどうかを見れば、エラーを出すべきかどうかがわかる。

たとえば、cases/compiler/objectLiteralIndexerErrors.tsは、エラーが出るのが想定されているので、baselines/reference/objectLiteralIndexerErrors.errors.txtが存在する、といった感じ。

最後に1つ自戒としての注意点を書いておくと、エラーが出力されてるからといって、ASTが出力されないわけではないってこと。 TSはf(みたいな入力途中の不完全なコードに対しても、ちゃんとASTを生成してくる。