テスト言語
テスト言語
導入
テストは言語設計者の作業の重要な部分です。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 を作成します。これにより、テストモデルを変換し、生成されたコードが期待される結果と一致するかどうかを確認できます。 詳細については、ジェネレーターテストセクションを参照してください。 現時点でこれらの側面のための組み込みテスト機能はありません。時間の経過とともに私たちのために働いてきたいくつかの習慣があります:
|
マイグレーション | jetbrains.mps.lang.test 言語を使用して MigrationTestCases を作成します。これらのテストケースでは、移行を実行するためのコードを記述します。 詳細は、移行テストセクションを参照してください。 |
作成をテストする
プロジェクトにテストモデルを追加する方法は 2 つあります。
1. 言語でテストアスペクトを作成する
これはセットアップが簡単ですが、新しく開始された MPS インスタンスで実行する必要がないテストのみを含めることができます。通常は単純な基本言語ユニットテストを保持できます。テストアスペクトを作成するには、言語ノードを右クリックし、New->Test Aspect
を選択します。
これで、テストアスペクトで単体テストの作成を開始できます。
テストアスペクトを右クリックすると、すべてのテストを実行するオプションが表示されます。テストレポートは、画面下部の実行パネルに表示されます。
2. テストモデルを作成する
このオプションを使用すると、柔軟性が高まります。新規または既存のソリューションでテストモデルを作成します。モデルのステレオタイプが tests に設定されていることを確認してください。
単体テストを作成できるようにするには、モデルのプロパティを開き、jetbrains.mps.baselanguage.unitTest 言語を追加します。言語(ノード)テストを作成するには、jetbrains.mps.lang.test 言語を追加します。
さらに、テストモデルを含むソリューションに種類セットがあることを確認する必要があります。他の 2 つのオプション (Core プラグインまたは Editor プラグイン ) のいずれも必要ない場合は、通常、Other を選択します。
モデルを右クリックすると、新しい単体テストまたは言語テストを作成できます。利用可能なすべての根本的概念を参照してください。
BTestCase による単体テスト
BaseLanguage テストケースに関しては、baseLanguage で記述された単体テストを表します。JUnit に精通している人はすぐに家に帰ります。
BTestCase には 4 つのセクションがあります。1 つはテストメソッドで再利用されるテストメンバー(フィールド)を指定するセクション、1 つは初期化コードを指定するセクション、1 つはクリーンアップコード用、最後に実際のテストメソッド用のセクションです。この言語は、コード補完が明らかにするいくつかの便利なアサーションステートメントも提供します。
TestInfo
たとえば、ノードテストやエディターテストなどの一部のテストでは、そのテストが属する MPS プロジェクトにアクセスする必要があります。ほとんどの場合、MPS は現在のプロジェクトを独自に見つけることができますが、テストモデルのルートにある TestInfo ノード内で明示的なプロジェクトの場所を指定することもできます。これは、JUnit テストを実行するすべてのモードに適用されます。
IDE からインプロセスとアウトプロセスの両方で実行する場合、開くプロジェクトは現在開いているプロジェクトであると想定されます。
<launchtests> タスクから実行: プロジェクトパスは、タスクの追加オプション「プロジェクトパス」として指定できます。指定しない場合は、現在のプロジェクトのホームディレクトリに対応する ${basedir} が使用されます。
上記のどちらも使用できない特別なケースでは、システムプロパティ -Dmps.test.project.path を使用してプロジェクトの場所を指定できる機能があります。
カスタム TestInfo ノードを提供する場合、特にプロジェクトパス属性に注目する価値があります。ここでは、プロジェクトルートへのパスを絶対パスまたは相対パスとして、あるいは MPS で定義されたパス変数への参照として提供する必要があります ( プロジェクト設定 -> パス変数 )。
パス変数を Ant スクリプトで使用できるようにするには、ビルドファイル内で mps.macro.
接頭辞を付けて定義します ( 以下の例を参照)。
言語定義のテスト面
ノードテスト
NodesTestCase には、次の 3 つのセクションがあります。
最初のコードには、検証する必要のあるコードが含まれています。テストメソッドのセクションには、最初のセクションで指定されたノードをさらに調査する baseLanguage コードが含まれる場合があります。ユーティリティメソッドセクションは、通常はテストメソッド から呼び出される再利用可能な baseLanguage コードを保持する場合があります。
正確さをチェックする
型システムが型を正しく計算し、適切なエラーと警告が報告されることをテストするには、最初に目的の言語でコードを記述します。次に、正確性をテストするノードを選択し、ノード操作の追加テストアノテーションインテンションを選択します。
これは check 属性でコードにアノテーションを付け、チェックのタイプを設定することによってより具体的にされることができます:
for error messages オプションは、チェックされたノード内の潜在的なエラーメッセージがテストの失敗として報告されることを保証します。したがって、与えられた例では、スクリプト全体にエラーがないことを確認しています。
他のオプションでは、次のことができます。
エラーがあります - 特定のエラーがノードで報告されるようにします
予想されるタイプ - アノテーション付きノードが指定されたタイプを持つことが予想されることを確認します
情報があります。特定の情報メッセージがノードで報告されるようにします
タイプがあります。アノテーション付きノードが指定されたタイプであることを確認します
タイプがあります。アノテーション付きノードが指定されたタイプの 1 つであることを確認します
型システムエラーがあります - 指定された型システムエラーがアノテーション付きノードで報告されるようにします
警告あり - 特定の警告がノードで報告されるようにします
型システムとデータフローのエラーと警告をチェックする
一方、特定のノードが MPS によってエラーまたは警告があると正しく報告されていることをテストする場合は、エラーあり / 警告ありオプションを使用します。
これは、警告とエラーの両方で機能します。単一のアノテーションで複数の警告とエラーを宣言できます。
エラー / 警告を報告すると予想されるルールにチェックを結び付けることもできます。ノードにキャレットがあるときに Alt+Enter を押し、ルール参照を指定するオプションを選択します。
ルールの識別子が追加されました。Ctrl+Space でルールの定義に移動できます。
実行すると、テストは指定されたルールが実際にエラーを報告したものであることを確認します。
型システム固有のオプション
check コマンドには、計算されたノードの種類をテストするためのいくつかのオプションがあります。
複数の期待を簡単に組み合わせることができます。
テストスコープ
スコープテストアノテーションでは、有効範囲の規則によって正しい項目が適切な範囲に含まれることをテストで検証できます。
インスペクターパネルには、完了メニューに表示する必要があり、アノテーション付きセルの有効なターゲットである予想アイテムのリストが保持されます。
テスト方法と実用方法
テストメソッドはラベルを通してあなたのテストのノードを参照するかもしれません。インテンションを使用してラベルをノードに割り当てます。
その後、ラベルはテストメソッドで利用可能になります。
インスペクターで定義された追加オプション
インスペクターツールウィンドウには追加のオプションが用意されています。
インプロセスで実行可能 - これにより、テストの作成者は、テストスイート全体がインプロセスで実行を開始したときにテストの実行を停止できます。テストスイートは TestSetNotToBeExecutedInProcessException がスローされて終了します。これは、たとえば、テストで他のノードに触れて既存のプロジェクトに誤って損傷を与える可能性がある場合に便利です。
モデルアクセスモデル - テストに適用されるアクセス制御のタイプを指定します。
コマンド - テストはコマンドにラップされて実行されるため、モデルへの読み取り / 書き込みアクセスが許可されます
none - アクセス制御は適用されません
read - テストは読み取りアクションにラップされて実行されるため、モデルの読み取りが許可されます
unset - 移行に必要な、使用すべきではないメンテナンス値
その後、ラベルはテストメソッドで利用可能になります。
エディターテスト
エディターテストでは、エディターのダイナミズム(アクション、インテンション、置換)をテストできます。
空のエディターテストケースには、名前、オプションの説明、エディターの変換前のコード、変換後のコード(結果)、最後にコードセクションのコードを変換する実際のトリガーが必要です。
たとえば、ユーザーが閉じ括弧の後ろに「else{」と入力すると、BaseLanguage の IfStatement に「else」ブロックを追加できるかどうかをテストすると、次のようになります。
コードセクションでは、jetbrains.mps.lang.test 言語により、ユーザーが開始するアクションを呼び出すためのいくつかのオプションが提供されます。
type - 現在のキャレット位置にテキストを挿入します
キーを押す - キーの組み合わせを押すことをシミュレートします
アクションの呼び出し - アクションをトリガーします
インテンションを呼び出す - インテンションをトリガーする
YYY から選択したノードへのクイックフィックス XXX を呼び出す - インテンションメニューからエラー YYY に対して XXX という名前の指定されたクイックフィックスを呼び出します。クイックフィックスがメニューで使用できない場合は失敗します
選択したノードにクイックフィックス <only one available> を呼び出します - インテンションメニューで使用可能な唯一のクイックフィックスを呼び出します。0 個または複数のクイックフィックスが使用可能な場合は失敗します
明らかに、特別なテストコマンドをプレーンな BaseLanguage コードと組み合わせることができます。
コード内のキャレットの位置をマークするには、適切なインテンションを使用して、キャレットを目的の位置に配置します。
キャレット位置は、前後 のコードの両方で指定できます。
セルエディターのアノテーションには、アノテーション付きのエディターセル内のキャレットの位置を微調整するための追加のプロパティがあります。これらは、インスペクターパネルで設定できます。
エディターの状態を調べる
一部のエディターテストでは、エディターの状態をより徹底的にインスペクションする必要がある場合があります。エディターコンポーネント式を使用すると、キャレットにあるエディターコンポーネントにアクセスできます。次のサンプルのように、その状態をインスペクションしたり変更したりできます。
これはインテンションに適用可能な式であり、特定のインテンションを特定のエディターコンテキストで呼び出すことができるかどうかをテストできます。
モデル式とプロジェクト式をそれぞれ使用して、モデルとプロジェクトを取得することもできます。
2 段階削除のテスト
ノードの 2 フェーズ削除は、次のようにエディターコンポーネント式を使用してテストできます。
EditorTestUtils.runWithTwoStepDeletion は、2 段階削除を有効にしてローカルコンテキストを作成します。ユーザーは 2 段階の削除を自由にオンおよびオフにできるため、テストの一貫した環境が確保されることに注意してください。メソッドの 2 番目のブールパラメーターは、2 段階削除をオンにするかオフにするかを示します。
DeletionApproverUtil.isApprovedForDeletion- 現在のノードに対応するセルを取得し、テストは「approvedForDeletion」フラグです。
あるいは、ユーティリティクラスの助けを借りずにフラグをテストするには、component.getDeletionApprover() を使用します。「削除承認済み」フラグをテストする必要があるエディターセルを見つけて提供する必要があります。
移行テスト
移行テストを使用して、指定された入力を使用して移行スクリプトが期待どおりの結果を生成することを確認できます。
移行テストケースを作成するには、その名前とテストする移行スクリプトを指定する必要があります。多くの場合、個々の移行スクリプトを別々にテストするだけで十分ですが、移行が互いにどのように相互作用するかをテストする必要がある場合は、単一のテストケースで複数の移行スクリプトを安全に指定できます。
さらに、移行テストケースには、移行プロセスに渡されるノードと、移行の成果として出てくることが予想されるノードも含まれます。
実行すると、移行テストは次のように動作します。
入力ノードは、単一モデルの空のモジュールにルートとしてコピーされます。
移行スクリプトはそのモジュール上で実行されます。
移行後にそのモジュールに含まれているルートは、予想される出力と比較されます。
問題のマイグレーションの check() メソッドが、問題の空のリストを確実に返すようにするために呼び出されます。
移行テストを作成するプロセスを簡素化するために、現在デプロイされている移行スクリプトを使用して、期待される出力を入力ノードから自動的に生成できます。これを行うには、'入力から出力を生成' というインテンションを使用します。
ジェネレーターテスト
ジェネレーターはジェネレーターテストでテストすることができます。彼らのゴールは、ジェネレーターまたはジェネレーターのセットが、期待通りに変換を実行することを保証することです。IDE では、MPS、Ant ビルドスクリプトからの実行と同様に、インプロセス実行モードとアウトプロセス実行モードの両方がサポートされています。MPS のすべてのテストと同様に、ユーザーは以下を指定します。
入力モデルの形での前提条件
出力モデルの形でのジェネレーターの期待される出力
明示的なジェネレータープランの形式で入力モデルに適用するジェネレーターのセット。省略した場合は、暗黙的なジェネレータープランが使用されます。
jetbrains.mps.lang.test.generator を使用すると、GeneratorTests を作成できます。jetbrains.mps.lang.modelapi 言語を使用すると、モデル / モデルの名前 / 構文を使用して便利なモデル参照を作成できます。
ジェネレーターテストの構造には、すべてのモデル(入力、予測出力、オプションで生成計画を保持するモデル)を指定する必要がある引数というセクションと、目的の変換とマッチングを行うアサーションというセクションがあります。指定されています。
ジェネレーターの出力と予想される出力との一致に失敗すると、テストレポートでユーザに表示されます。
モデルマッチオプション
生成テストの実際の結果と期待される出力を比較する方法は、一致オプションで構成できます。
これらの一致オプションは、アサーションに関連付けることができます。
ルートノードの並べ替え
プロジェクトツールウィンドウには常にルートノードがアルファベット順にリストされるため、モデル内のルートノードの実際の物理的な順序は隠されます。デフォルトでは、モデルのルートノードの順序は、生成テスト中にモデルが比較されるときに重要になります。テストに合格するには、テストの一致オプションを変更するか、出力モデルのルートノードを手動で並べ替えて、ジェネレーターからの期待を反映することができます。
テストを実行する
内側 MPS
モデルでテストを実行するには、プロジェクトビューパネルでモデルを右クリックし、テストの実行を選択します。
モデルに jetbrains.mps.lang.test テストが含まれている場合、MPS の新しいインスタンスがバックグラウンドで静かに開始され (そのため、通常の baseLanguage ユニットテストと比較して、実行にかなりの時間がかかります)、テストはその新しい MPS インスタンスで実行されます。新しい実行構成が作成され、それを再利用したりカスタマイズしたりすることができます。
実行構成ダイアログには、テストのパフォーマンスを調整するためのオプションがあります。
デフォルト設定の場所を上書きする - キャッシュを保存するディレクトリを指定します。デフォルトでは、MPS は一時ディレクトリを選択します。ディレクトリは実行ごとにクリアされます。
同じプロセスで実行する - テストを高速化するために、テストはいわゆるインプロセスモードで実行できます。これは、MPS インスタンスを実行する必要があるテスト用に特別に設計されました。(例: 言語型システムテストの場合、MPS はノードのタイプをその場で安全にチェックできるはずです。)
テストを実行する 1 つの方法は、新しい MPS インスタンスをバックグラウンドで開始し、このインスタンスでテストを実行することです。このチェックボックスで有効になっている 2 番目の方法では、すべてのテストを同じ元の MPS プロセスで実行するため、新しいインスタンスを作成する必要はありません。
オプション同じプロセスで実行するが設定されている場合、テストは現在の MPS 環境で実行されます。これは、次のデフォルトです。
ノードテスト
エディターテスト
元の方法で(別のプロセスで)テストを実行するには、このオプションのチェックを外す必要があります。これは、次のデフォルトです。
移行テスト
生成テスト
ユニットテスト (BTestCases と JUnit のテストケース)
テストレポートは画面下部の実行パネルに表示されます。
JUnit 実行構成はテストを実行する前にデプロイするプラグインを受け入れます。ユーザーはテスト実行中にデプロイされるアイデアプラグインのリストを提供できます。前のタスク 'Assemble Plugins' は JUnit の実行構成でも利用できます。与えられたプラグインを自動的に構築し、アーティファクトを設定ディレクトリにコピーします。
ビルドスクリプトから
生成されたビルドスクリプトに、Ant を使用してテストを実行するために使用できるテスト ターゲットを提供させるには、jetbrains.mps.build.mps および jetbrains.mps.build.mps.tests 言語をビルドスクリプトにインポートする必要があります。、module-tests プラグインを使用して宣言し、テストモジュール構成を指定します。
デフォルトでは、MPS の JUnit テストは「vintage」および「jupiter」形式でテストレポートを生成します。さらに、オープンテストレポート形式は、オープンテストレポートの作成オプションを使用して明示的に有効にできます。オプションが true に設定されている場合、「junit-platform-events*-$BUILD_NAME$.xml」という名前のレポートファイルがプロジェクトディレクトリに作成されます。
Ant が JUnit に渡すマクロを定義するには(たとえば、テストの TestInfo ルートで使用するために)、mps.macro.
を頭に付けます。
関連ページ:
世代計画
世代計画:生成計画を使用すると、開発者は自分のモデルに望ましい生成順序を明示的に指定でき、生成プロセスをより適切に制御できます。目的相互ジェネレーターの優先順位の指定は、大規模なプロジェクトの場合には面倒になる可能性があります。さらに、優先順位を指定するために、関係する言語は、適切な相互依存関係を宣言することによって互いのことを知る必要があります。これにより、言語の (場合によっては望ましい) 独立性が損なわれます。生成計画では、生成ステップの適切な順序付けの責任が 1 か所 (生成計画) に...
MPS デバッガーを使う
デバッグ:MPS デバッガーは、カスタム言語用のデバッガーを作成するための API を提供します。MPS ディストリビューションに含まれている Java デバッガープラグインは、ユーザーが最終的に Base Language/Java に生成される言語で書かれているプログラムをデバッグすることを可能にします。下記のプラグインを使って MPS デバッガーの機能を説明します。これらはすべて API を介して他の言語でも利用できます。実行 java アプリケーションをデバッグする方法の説明から始めます...
依存関係
モデル間の依存関係を管理することは不可欠です。そのトピックに関する情報については、左側のパネルを参照してください。テスト言語依存関係を正しくする