MPS 2024.1 ヘルプ

テスト言語

テスト言語

導入

テストは言語設計者の作業の重要な部分です。MPS が優れているためには、BaseLanguage コードと言語の両方のテスト機能を提供する必要があります。jetbrains.mps.baselanguage.unitTest 言語を使用すると、JUnit -like ユニットテストで BaseLanguage コードをテストできますが、言語テスト言語の jetbrains.mps.lang.test は、言語テストを作成するための便利なインターフェースを提供します。

クイックナビゲーションテーブル

言語定義のさまざまな側面がさまざまな方法でテストされています。

言語定義の側面

テストする方法

インテンション

アクション

サイドトランスフォーム

エディター

ActionMaps

KeyMaps

EditorTestCases を作成する jetbrains.mps.lang.test 言語を使用してください。最初のコードを提供することでステージを設定し、最初のコードに対して実行する一連の編集アクションを定義し、別のコードとして期待される結果を提供します。テストの期待される出力と実際の出力の違いは、エラーとして報告されます。

詳細については、エディターテストセクションを参照してください。

制約

スコープ

型システム

データフロー

jetbrains.mps.lang.test 言語を使用して NodesTestCases を作成します。これらのテストケースでは、「正しい」コードのスニペットを記述し、エラーや警告が報告されないことを確認します。同様に、「無効な」コード片を記述し、正しいノードでエラーまたは警告が報告されることを確認します。

詳細については、ノードテストセクションを参照してください。

生成プログラム

TextGen

使用 言語を使用して GeneratorTests を作成します。これにより、テストモデルを変換し、生成されたコードが期待される結果と一致するかどうかを確認できます。

詳細については、ジェネレーターテストセクションを参照してください。

現時点でこれらの側面のための組み込みテスト機能はありません。時間の経過とともに私たちのために働いてきたいくつかの習慣があります:

  • おそらく、生成プロセスをチェックするための最も合理的な方法は、正しい生成結果がわかっているモデルを生成し、生成された出力を予想されたものと比較することです。例: 生成コードが VCS に格納されている場合は、テストを実行するたびに違いを確認できます。

  • また、ジェネレーターの重要なケースを表すコードスニペットを用意し、ジェネレーターがそれらから出力を正常に生成するかどうか、失敗するかどうかを確認することもできます。

  • 生成されたコードをコンパイルして実行すると、ジェネレーターの正しさについての信頼性が高まる可能性があります。

マイグレーション

jetbrains.mps.lang.test 言語を使用して MigrationTestCases を作成します。これらのテストケースでは、移行を実行するためのコードを記述します。

詳細は、移行テストセクションを参照してください。

作成をテストする

プロジェクトにテストモデルを追加する方法は 2 つあります。

1. 言語でテストアスペクトを作成する

これはセットアップが簡単ですが、新しく開始された MPS インスタンスで実行する必要がないテストのみを含めることができます。通常は単純な基本言語ユニットテストを保持できます。テストアスペクトを作成するには、言語ノードを右クリックし、New->Test Aspect を選択します。

T2.png

これで、テストアスペクトで単体テストの作成を開始できます。

T1.png

テストアスペクトを右クリックすると、すべてのテストを実行するオプションが表示されます。テストレポートは、画面下部の実行パネルに表示されます。

2. テストモデルを作成する

このオプションを使用すると、柔軟性が高まります。新規または既存のソリューションでテストモデルを作成します。モデルのステレオタイプが tests に設定されていることを確認してください。

T3.png

単体テストを作成できるようにするには、モデルのプロパティを開き、jetbrains.mps.baselanguage.unitTest 言語を追加します。言語(ノード)テストを作成するには、jetbrains.mps.lang.test 言語を追加します。

T4.png

さらに、テストモデルを含むソリューションに種類セットがあることを確認する必要があります。他の 2 つのオプション (Core プラグインまたは Editor プラグイン ) のいずれも必要ない場合は、通常、Other を選択します。

T8.png

モデルを右クリックすると、新しい単体テストまたは言語テストを作成できます。利用可能なすべての根本的概念を参照してください。

T5.png
T6.png

BTestCase による単体テスト

BaseLanguage テストケースに関しては、baseLanguage で記述された単体テストを表します。JUnit に精通している人はすぐに家に帰ります。

T7.png

BTestCase には 4 つのセクションがあります。1 つはテストメソッドで再利用されるテストメンバー(フィールド)を指定するセクション、1 つは初期化コードを指定するセクション、1 つはクリーンアップコード用、最後に実際のテストメソッド用のセクションです。この言語は、コード補完が明らかにするいくつかの便利なアサーションステートメントも提供します。

TestInfo

たとえば、ノードテストエディターテストなどの一部のテストでは、そのテストが属する MPS プロジェクトにアクセスする必要があります。ほとんどの場合、MPS は現在のプロジェクトを独自に見つけることができますが、テストモデルのルートにある TestInfo ノード内で明示的なプロジェクトの場所を指定することもできます。これは、JUnit テストを実行するすべてのモードに適用されます。

  • IDE からインプロセスとアウトプロセスの両方で実行する場合、開くプロジェクトは現在開いているプロジェクトであると想定されます。

  • <launchtests> タスクから実行: プロジェクトパスは、タスクの追加オプション「プロジェクトパス」として指定できます。指定しない場合は、現在のプロジェクトのホームディレクトリに対応する ${basedir} が使用されます。

  • 上記のどちらも使用できない特別なケースでは、システムプロパティ -Dmps.test.project.path を使用してプロジェクトの場所を指定できる機能があります。

testInfox1.png

カスタム TestInfo ノードを提供する場合、特にプロジェクトパス属性に注目する価値があります。ここでは、プロジェクトルートへのパスを絶対パスまたは相対パスとして、あるいは MPS で定義されたパス変数への参照として提供する必要があります ( プロジェクト設定 -> パス変数 )。

pathVariables1.png

パス変数を Ant スクリプトで使用できるようにするには、ビルドファイル内で mps.macro. 接頭辞を付けて定義します ( 以下の例を参照)。

言語定義のテスト面

ノードテスト

NodesTestCase には、次の 3 つのセクションがあります。

T10.png

最初のコードには、検証する必要のあるコードが含まれています。テストメソッドのセクションには、最初のセクションで指定されたノードをさらに調査する baseLanguage コードが含まれる場合があります。ユーティリティメソッドセクションは、通常はテストメソッド から呼び出される再利用可能な baseLanguage コードを保持する場合があります。

正確さをチェックする

型システムが型を正しく計算し、適切なエラーと警告が報告されることをテストするには、最初に目的の言語でコードを記述します。次に、正確性をテストするノードを選択し、ノード操作の追加テストアノテーションインテンションを選択します。

T11.png
T12.png
T13.png

これは check 属性でコードにアノテーションを付け、チェックのタイプを設定することによってより具体的にされることができます:

T14.png
T15.png

for error messages オプションは、チェックされたノード内の潜在的なエラーメッセージがテストの失敗として報告されることを保証します。したがって、与えられた例では、スクリプト全体にエラーがないことを確認しています。

他のオプションでは、次のことができます。

  • エラーがあります - 特定のエラーがノードで報告されるようにします

  • 予想されるタイプ - アノテーション付きノードが指定されたタイプを持つことが予想されることを確認します

  • 情報があります。特定の情報メッセージがノードで報告されるようにします

  • タイプがあります。アノテーション付きノードが指定されたタイプであることを確認します

  • タイプがあります。アノテーション付きノードが指定されたタイプの 1 つであることを確認します

  • 型システムエラーがあります - 指定された型システムエラーがアノテーション付きノードで報告されるようにします

  • 警告あり - 特定の警告がノードで報告されるようにします

型システムとデータフローのエラーと警告をチェックする

一方、特定のノードが MPS によってエラーまたは警告があると正しく報告されていることをテストする場合は、エラーあり / 警告ありオプションを使用します。

T16.png
T17.png

これは、警告とエラーの両方で機能します。単一のアノテーションで複数の警告とエラーを宣言できます。

T26_1.png

エラー / 警告を報告すると予想されるルールにチェックを結び付けることもできます。ノードにキャレットがあるときに Alt+Enter を押し、ルール参照を指定するオプションを選択します。

T18.png
T19.png

ルールの識別子が追加されました。Ctrl+Space でルールの定義に移動できます。

T29.png

実行すると、テストは指定されたルールが実際にエラーを報告したものであることを確認します。

型システム固有のオプション

check コマンドには、計算されたノードの種類をテストするためのいくつかのオプションがあります。

T100.png
T101.png

複数の期待を簡単に組み合わせることができます。

T37.png

テストスコープ

スコープテストアノテーションでは、有効範囲の規則によって正しい項目が適切な範囲に含まれることをテストで検証できます。

T102.png

インスペクターパネルには、完了メニューに表示する必要があり、アノテーション付きセルの有効なターゲットである予想アイテムのリストが保持されます。

T103.png
T104.png

テスト方法と実用方法

テストメソッドはラベルを通してあなたのテストのノードを参照するかもしれません。インテンションを使用してラベルをノードに割り当てます。

T32.png

その後、ラベルはテストメソッドで利用可能になります。

T33.png

インスペクターで定義された追加オプション

インスペクターツールウィンドウには追加のオプションが用意されています。

  • インプロセスで実行可能 - これにより、テストの作成者は、テストスイート全体がインプロセスで実行を開始したときにテストの実行を停止できます。テストスイートは TestSetNotToBeExecutedInProcessException がスローされて終了します。これは、たとえば、テストで他のノードに触れて既存のプロジェクトに誤って損傷を与える可能性がある場合に便利です。

  • モデルアクセスモデル - テストに適用されるアクセス制御のタイプを指定します。

    • コマンド - テストはコマンドにラップされて実行されるため、モデルへの読み取り / 書き込みアクセスが許可されます

    • none - アクセス制御は適用されません

    • read - テストは読み取りアクションにラップされて実行されるため、モデルの読み取りが許可されます

    • unset - 移行に必要な、使用すべきではないメンテナンス値

T32.png

その後、ラベルはテストメソッドで利用可能になります。

T33.png

エディターテスト

エディターテストでは、エディターのダイナミズム(アクション、インテンション、置換)をテストできます。

T20.png

空のエディターテストケースには、名前、オプションの説明、エディターの変換のコード、変換のコード(結果)、最後にコードセクションのコードを変換する実際のトリガーが必要です。

T21.png

たとえば、ユーザーが閉じ括弧の後ろに「else{」と入力すると、BaseLanguageIfStatement に「else」ブロックを追加できるかどうかをテストすると、次のようになります。

T21a.png

コードセクションでは、jetbrains.mps.lang.test 言語により、ユーザーが開始するアクションを呼び出すためのいくつかのオプションが提供されます。

  • type - 現在のキャレット位置にテキストを挿入します

  • キーを押す - キーの組み合わせを押すことをシミュレートします

  • アクションの呼び出し - アクションをトリガーします

  • インテンションを呼び出す - インテンションをトリガーする

  • YYY から選択したノードへのクイックフィックス XXX を呼び出す - インテンションメニューからエラー YYY に対して XXX という名前の指定されたクイックフィックスを呼び出します。クイックフィックスがメニューで使用できない場合は失敗します

  • 選択したノードにクイックフィックス <only one available> を呼び出します - インテンションメニューで使用可能な唯一のクイックフィックスを呼び出します。0 個または複数のクイックフィックスが使用可能な場合は失敗します

T22.png

明らかに、特別なテストコマンドをプレーンな BaseLanguage コードと組み合わせることができます。

コード内のキャレットの位置をマークするには、適切なインテンションを使用して、キャレットを目的の位置に配置します。

T23.png

キャレット位置は、前後 のコードの両方で指定できます。

T25.png

セルエディターのアノテーションには、アノテーション付きのエディターセル内のキャレットの位置を微調整するための追加のプロパティがあります。これらは、インスペクターパネルで設定できます。

エディターの状態を調べる

一部のエディターテストでは、エディターの状態をより徹底的にインスペクションする必要がある場合があります。エディターコンポーネント式を使用すると、キャレットにあるエディターコンポーネントにアクセスできます。次のサンプルのように、その状態をインスペクションしたり変更したりできます。

ec1.png
ec2.png
ec3.png
ec4.png

これはインテンションに適用可能な式であり、特定のインテンションを特定のエディターコンテキストで呼び出すことができるかどうかをテストできます。

iiap.png

モデル式プロジェクト式をそれぞれ使用して、モデルプロジェクトを取得することもできます。

2 段階削除のテスト

ノードの 2 フェーズ削除は、次のようにエディターコンポーネント式を使用してテストできます。

EditorTestUtil.runWithTwoStepDeletion({ => invoke action -> Delete assert true DeletionApproverUtil.isApprovedForDeletion(editor component.getEditorContext(), editor component.getSelectedNode()); assert true editor component.getDeletionApprover().isApprovedForDeletion(editor component.findNodeCell(editor component.getSelectedNode())); invoke action -> Delete }, true);
  • EditorTestUtils.runWithTwoStepDeletion は、2 段階削除を有効にしてローカルコンテキストを作成します。ユーザーは 2 段階の削除を自由にオンおよびオフにできるため、テストの一貫した環境が確保されることに注意してください。メソッドの 2 番目のブールパラメーターは、2 段階削除をオンにするかオフにするかを示します。

  • DeletionApproverUtil.isApprovedForDeletion- 現在のノードに対応するセルを取得し、テストは「approvedForDeletion」フラグです。

  • あるいは、ユーティリティクラスの助けを借りずにフラグをテストするには、component.getDeletionApprover() を使用します。「削除承認済み」フラグをテストする必要があるエディターセルを見つけて提供する必要があります。

移行テスト

移行テストを使用して、指定された入力を使用して移行スクリプトが期待どおりの結果を生成することを確認できます。

new-migration-test.png

移行テストケースを作成するには、その名前とテストする移行スクリプトを指定する必要があります。多くの場合、個々の移行スクリプトを別々にテストするだけで十分ですが、移行が互いにどのように相互作用するかをテストする必要がある場合は、単一のテストケースで複数の移行スクリプトを安全に指定できます。

empty-migration-test.png

さらに、移行テストケースには、移行プロセスに渡されるノードと、移行の成果として出てくることが予想されるノードも含まれます。

input-output.png

実行すると、移行テストは次のように動作します。

  1. 入力ノードは、単一モデルの空のモジュールにルートとしてコピーされます。

  2. 移行スクリプトはそのモジュール上で実行されます。

  3. 移行後にそのモジュールに含まれているルートは、予想される出力と比較されます。

  4. 問題のマイグレーションの check() メソッドが、問題の空のリストを確実に返すようにするために呼び出されます。

移行テストを作成するプロセスを簡素化するために、現在デプロイされている移行スクリプトを使用して、期待される出力を入力ノードから自動的に生成できます。これを行うには、'入力から出力を生成' というインテンションを使用します。

generate-output.png

ジェネレーターテスト

ジェネレーターはジェネレーターテストでテストすることができます。彼らのゴールは、ジェネレーターまたはジェネレーターのセットが、期待通りに変換を実行することを保証することです。IDE では、MPS、Ant ビルドスクリプトからの実行と同様に、インプロセス実行モードとアウトプロセス実行モードの両方がサポートされています。MPS のすべてのテストと同様に、ユーザーは以下を指定します。

  1. 入力モデルの形での前提条件

  2. 出力モデルの形でのジェネレーターの期待される出力

  3. 明示的なジェネレータープランの形式で入力モデルに適用するジェネレーターのセット。省略した場合は、暗黙的なジェネレータープランが使用されます。

jetbrains.mps.lang.test.generator を使用すると、GeneratorTests を作成できます。jetbrains.mps.lang.modelapi 言語を使用すると、モデル / モデルの名前 / 構文を使用して便利なモデル参照を作成できます。

GT1.png

ジェネレーターテストの構造には、すべてのモデル(入力、予測出力、オプションで生成計画を保持するモデル)を指定する必要がある引数というセクションと、目的の変換とマッチングを行うアサーションというセクションがあります。指定されています。

ジェネレーターの出力と予想される出力との一致に失敗すると、テストレポートでユーザに表示されます。

GT2.png

モデルマッチオプション

生成テストの実際の結果と期待される出力を比較する方法は、一致オプションで構成できます。

MatchOptions.png

これらの一致オプションは、アサーションに関連付けることができます。

ルートノードの並べ替え

プロジェクトツールウィンドウには常にルートノードがアルファベット順にリストされるため、モデル内のルートノードの実際の物理的な順序は隠されます。デフォルトでは、モデルのルートノードの順序は、生成テスト中にモデルが比較されるときに重要になります。テストに合格するには、テストの一致オプションを変更するか、出力モデルのルートノードを手動で並べ替えて、ジェネレーターからの期待を反映することができます。

ReorderNodes1.png


ReorderNodes2.png

テストを実行する

内側 MPS

モデルでテストを実行するには、プロジェクトビューパネルでモデルを右クリックし、テストの実行を選択します。

T39.png

モデルに jetbrains.mps.lang.test テストが含まれている場合、MPS の新しいインスタンスがバックグラウンドで静かに開始され (そのため、通常の baseLanguage ユニットテストと比較して、実行にかなりの時間がかかります)、テストはその新しい MPS インスタンスで実行されます。新しい実行構成が作成され、それを再利用したりカスタマイズしたりすることができます。

testrunconfig.png

実行構成ダイアログには、テストのパフォーマンスを調整するためのオプションがあります。

  • デフォルト設定の場所を上書きする - キャッシュを保存するディレクトリを指定します。デフォルトでは、MPS は一時ディレクトリを選択します。ディレクトリは実行ごとにクリアされます。

  • 同じプロセスで実行する - テストを高速化するために、テストはいわゆるインプロセスモードで実行できます。これは、MPS インスタンスを実行する必要があるテスト用に特別に設計されました。(例: 言語型システムテストの場合、MPS はノードのタイプをその場で安全にチェックできるはずです。)

    テストを実行する 1 つの方法は、新しい MPS インスタンスをバックグラウンドで開始し、このインスタンスでテストを実行することです。このチェックボックスで有効になっている 2 番目の方法では、すべてのテストを同じ元の MPS プロセスで実行するため、新しいインスタンスを作成する必要はありません。

    オプション同じプロセスで実行するが設定されている場合、テストは現在の MPS 環境で実行されます。これは、次のデフォルトです。

    • ノードテスト

    • エディターテスト

    元の方法で(別のプロセスで)テストを実行するには、このオプションのチェックを外す必要があります。これは、次のデフォルトです。

    • 移行テスト

    • 生成テスト

    • ユニットテスト (BTestCases と JUnit のテストケース)

    テストレポートは画面下部の実行パネルに表示されます。

  • JUnit 実行構成はテストを実行する前にデプロイするプラグインを受け入れます。ユーザーはテスト実行中にデプロイされるアイデアプラグインのリストを提供できます。前のタスク 'Assemble Plugins' は JUnit の実行構成でも利用できます。与えられたプラグインを自動的に構築し、アーティファクトを設定ディレクトリにコピーします。

T41.png

ビルドスクリプトから

生成されたビルドスクリプトに、Ant を使用してテストを実行するために使用できるテスト ターゲットを提供させるには、jetbrains.mps.build.mps および jetbrains.mps.build.mps.tests 言語をビルドスクリプトにインポートする必要があります。、module-tests プラグインを使用して宣言し、テストモジュール構成を指定します。

testScript1.png

デフォルトでは、MPS の JUnit テストは「vintage」および「jupiter」形式でテストレポートを生成します。さらに、オープンテストレポート形式は、オープンテストレポートの作成オプションを使用して明示的に有効にできます。オプションが true に設定されている場合、「junit-platform-events*-$BUILD_NAME$.xml」という名前のレポートファイルがプロジェクトディレクトリに作成されます。

Ant が JUnit に渡すマクロを定義するには(たとえば、テストの TestInfo ルートで使用するために)、mps.macro. を頭に付けます。

image2016-10-13-17-29-27.png

関連ページ:

世代計画

世代計画:生成計画を使用すると、開発者は自分のモデルに望ましい生成順序を明示的に指定でき、生成プロセスをより適切に制御できます。目的相互ジェネレーターの優先順位の指定は、大規模なプロジェクトの場合には面倒になる可能性があります。さらに、優先順位を指定するために、関係する言語は、適切な相互依存関係を宣言することによって互いのことを知る必要があります。これにより、言語の (場合によっては望ましい) 独立性が損なわれます。生成計画では、生成ステップの適切な順序付けの責任が 1 か所 (生成計画) に...

MPS デバッガーを使う

デバッグ:MPS デバッガーは、カスタム言語用のデバッガーを作成するための API を提供します。MPS ディストリビューションに含まれている Java デバッガープラグインは、ユーザーが最終的に Base Language/Java に生成される言語で書かれているプログラムをデバッグすることを可能にします。下記のプラグインを使って MPS デバッガーの機能を説明します。これらはすべて API を介して他の言語でも利用できます。実行 java アプリケーションをデバッグする方法の説明から始めます...

依存関係

モデル間の依存関係を管理することは不可欠です。そのトピックに関する情報については、左側のパネルを参照してください。テスト言語依存関係を正しくする