テストガイド

テストの実行

# Run all tests
./gradlew test

# Run tests with coverage report
./gradlew test koverHtmlReport

# View coverage report
open build/reports/kover/html/index.html

テスト構成

テストは src/test/kotlin/com/rescript/plugin/ に配置され、ソースコードのパッケージ構成をミラーしています:

src/test/kotlin/com/rescript/plugin/
├── highlight/
│   ├── RescriptSyntaxHighlighterTest.kt
│   └── RescriptBraceMatcherTest.kt
├── lang/
│   ├── RescriptLexerTest.kt
│   └── RescriptParserTest.kt
├── folding/
│   └── RescriptFoldingBuilderTest.kt
├── ...

テストの作成

テスト規約

  • ファイル命名: <TargetClass>Test.kt

  • 配置場所: テスト対象クラスと同じパッケージ

  • フレームワーク: JUnit 5 と IntelliJ テストフィクスチャ

IntelliJ テストフィクスチャ

ほとんどのテストは IntelliJ Platform のテスト基底クラスを継承しています:

class RescriptMyFeatureTest : BasePlatformTestCase() {

    override fun getTestDataPath(): String = "src/test/testData/myfeature"

    fun testBasicCase() {
        // Configure test fixture with a ReScript file
        myFixture.configureByText("Test.res", "let x = 1")
        // Invoke the feature and assert results
    }
}

テストデータファイル

テストデータファイルは src/test/testData/<feature>/ に配置します:

src/test/testData/
├── folding/
│   ├── module.res
│   └── comments.res
├── highlighting/
│   └── keywords.res
└── ...

レクサーテスト

レクサーが正しいトークンシーケンスを生成することをテストします:

fun testKeywords() {
    val lexer = RescriptLexer()
    lexer.start("let x = 1")
    assertEquals(RescriptTokenTypes.LET, lexer.tokenType)
    lexer.advance()
    // ... continue checking tokens
}

パーサーテスト

パーサーが正しい PSI 構造を生成することをテストします:

fun testLetDeclaration() {
    myFixture.configureByText("Test.res", "let x = 1")
    val file = myFixture.file
    val declarations = PsiTreeUtil.findChildrenOfType(file, RescriptLetDeclaration::class.java)
    assertEquals(1, declarations.size)
}

統合テスト

統合テストは IntelliJ Platform のテストインフラを使用して、PSI ツリー、エディタフィクスチャ、ファイルベースのテストデータを含む実際の IDE 環境で機能を検証します。

ユニットテストと統合テストの比較

観点

ユニットテスト

統合テスト

基底クラス

なし、または素の JUnit

BasePlatformTestCase

速度

高速(IDE の起動不要)

低速(IDE プラットフォームの初期化あり)

スコープ

単一のクラス / 関数

IDE コンテキストでの機能のエンドツーエンド

使用する場面

純粋なロジックのテスト(レクサートークン、ユーティリティ関数)

PSI、エディタ、またはフィクスチャと連携する機能のテスト

BasePlatformTestCase パターン

統合テストは BasePlatformTestCase を継承します。このクラスはエディタ、PSI インフラ、プロジェクトモデルを備えた軽量な IDE 環境を起動します:

class RescriptMyFeatureIntegrationTest : BasePlatformTestCase() {

    override fun getTestDataPath(): String = "src/test/testData/myfeature"

    fun testFeatureWithInlineCode() {
        // Configure editor with inline ReScript code
        myFixture.configureByText("Test.res", """
            let x = 1
            module M = {
              let y = 2
            }
        """.trimIndent())

        // Invoke the feature and assert results
        // e.g., myFixture.testStructureView { ... }
    }

    fun testFeatureWithTestDataFile() {
        // Load a test data file from getTestDataPath()
        myFixture.configureByFile("Example.res")
        // Assert against the loaded file
    }
}

主要なメソッド:

  • myFixture.configureByText(filename, content) — メモリ上にファイルを作成し、エディタで開く

  • myFixture.configureByFile(filename)testDataPath ディレクトリからファイルを読み込む

  • myFixture.testStructureView { view -> ... } — ストラクチャービューを開き、その内容を検証する

  • myFixture.testHighlighting(...) — ハイライトを実行し、アノテーションを確認する

統合テストクラス

プロジェクトには以下の統合テストカテゴリが含まれています:

テストクラス

機能

アサーション例

RescriptHighlightingIntegrationTest

シンタックスハイライト

トークンの色が期待される属性と一致する

RescriptFoldingBuilderIntegrationTest

コード折りたたみ

折りたたみ領域がテストデータ内の <fold> マーカーと一致する

RescriptStructureViewIntegrationTest

ストラクチャービュー

ツリーに期待される宣言が含まれている

RescriptIndentIntegrationTest

自動インデント

Enter キー押下後のインデントレベル

RescriptParserIntegrationTest

パーサー + PSI ツリー

PSI ツリーが期待される構造と一致する

RescriptLexerIntegrationTest

レクサートークンストリーム

ファイル全体のトークンシーケンスが期待値と一致する

testData ディレクトリ

テストデータファイルは src/test/testData/ 配下に機能ごとに整理されています:

src/test/testData/
├── folding/           # .res files with <fold> markers
├── highlighting/      # .res files for highlighting tests
├── structure/         # .res files for structure view tests
├── indent/            # .res files for indentation tests
├── parser/            # .res files for parser tests
└── lexer/             # .res files for lexer tests

各テストクラスは getTestDataPath() でデータディレクトリを指定します。テストデータファイルは通常の .res ファイルで、フレームワーク支援のアサーション用に特殊なマーカー(例: <fold text="...">)が含まれる場合があります。

テストカバレッジ

プロジェクトはコードカバレッジに Kover を使用しています。

# Generate HTML report
./gradlew koverHtmlReport

# Generate XML report (used by CI)
./gradlew koverXmlReport

カバレッジレポートは build/reports/kover/html/ に生成されます。

カバレッジ要件

  • 新しいコードにはテストカバレッジが必要です

  • CI がプルリクエストでカバレッジを報告します

  • 例外: UI コンポーネント (Swing)、実行中のサーバーが必要な LSP 統合クラス

UI テスト (Remote-Robot)

プロジェクトには、エンドツーエンドの IDE テストと Marketplace 用スクリーンショットの自動キャプチャのために IntelliJ Remote-Robot を使用した UI テストが含まれています。

前提条件

  • macOS: Java にアクセシビリティ権限を付与してください(システム設定 > プライバシーとセキュリティ > アクセシビリティ)

  • src/uiTest/testData/sample-project/ のサンプルプロジェクトに npm 依存関係をインストールしておく必要があります:

cd src/uiTest/testData/sample-project
npm install

UI テストの実行

UI テストは 2 段階のプロセスが必要です — テストが接続する前に IDE が起動している必要があります:

# Terminal 1: Start the IDE with Remote-Robot server (port 8082)
./gradlew runIdeForUiTests

# Terminal 2: Open the sample project in the IDE, then run the tests
./gradlew uiTest

スクリーンショット出力

MarketplaceScreenshotTest クラスは、プラグインの主要機能を紹介する 11 枚のスクリーンショットをキャプチャします。スクリーンショットは build/screenshots/ に保存されます:

スクリーンショット

機能

01-syntax-highlighting.png

ReScript コードの色付け

02-code-completion.png

LSP 補完ポップアップ

03-error-lens.png

インラインのエラー/警告表示

04-inlay-hints.png

型推論ヒント

05-structure-view.png

ファイルシンボルツリー

06-code-vision.png

関数の型注釈

07-jsx-support.png

JSX シンタックスハイライト

08-project-view.png

.resi ネストとコンパイル済み JS

09-quick-fix-intention.png

Alt+Enter インテンションメニュー

10-hover-documentation.png

型情報とドキュメント

11-repl.png

インタラクティブ REPL ツールウィンドウ

テスト構成

UI テストは別のソースセット(src/uiTest/)にあり、./gradlew test では実行されません:

src/uiTest/kotlin/com/rescript/plugin/uitest/
├── UiTestBase.kt                          # Base class (connection, screenshots)
├── fixtures/
│   └── IdeFixtures.kt                     # IDE component fixtures
└── screenshot/
    └── MarketplaceScreenshotTest.kt       # Marketplace screenshot capture

備考

  • UI テストは CI に含まれていません(ディスプレイが必要なため)

  • uiTest ソースセットは Kover カバレッジから除外されています

  • スクリーンショットは Marketplace での見栄えのために Darcula テーマを使用しています

CI テスト

CI パイプラインはすべてのプッシュと PR で自動的にテストを実行します:

  1. ./gradlew test koverXmlReport koverHtmlReport

  2. Kover レポートアクションを通じて PR でカバレッジが報告されます

  3. テスト結果はアーティファクトとしてアップロードされます