このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
カスタム プラグインを使ったテストの並列実行
この例では、テストの並列実行をサポートするカスタム プラグインの作成方法を説明します。カスタム プラグインは、テスト スイートのパスと失敗のアサーション数をカウントします。TestRunner
インスタンスを拡張するため、プラグインは matlab.unittest.plugins.TestRunnerPlugin
クラスの特定メソッドをオーバーライドします。さらに、テストの並列実行をサポートするため、プラグインは matlab.unittest.plugins.Parallelizable
インターフェイスをサブクラス化します。テストの並列実行には、Parallel Computing Toolbox™ が必要です。
プラグイン クラスの作成
現在のフォルダー内の AssertionCountingPlugin.m
という名前のファイルに、TestRunnerPlugin
クラスと Parallelizable
クラスの両方から継承する、並列化可能なプラグイン クラス AssertionCountingPlugin
を作成します。AssertionCountingPlugin
の完全なコードについては、プラグイン クラス定義を参照してください。
パスと失敗のアサーション数を追跡するには、properties
ブロック内で 4 つの読み取り専用プロパティを定義します。現在の並列プールの MATLAB® ワーカーはそれぞれ NumPassingAssertions
と NumFailingAssertions
を使用して、配列 TestSuite
の一部を実行するときに、パスと失敗のアサーション数を追跡します。MATLAB クライアントは FinalizedNumPassingAssertions
と FinalizedNumFailingAssertions
を使用して異なるワーカーからの結果を集計し、テスト セッションの最後にパスと失敗のアサーション数の合計をレポートします。
properties (SetAccess = private) NumPassingAssertions NumFailingAssertions FinalizedNumPassingAssertions FinalizedNumFailingAssertions end
テスト セッションの実行の拡張
配列 TestSuite
全体の実行を拡張するには、protected
アクセスが指定された methods
ブロック内で runSession
メソッドをオーバーライドします。runSession
は Test
要素数の合計についての情報を表示し、プラグインでテキスト出力の生成に使用するプロパティを初期化し、スーパークラス メソッドを呼び出してテスト実行全体をトリガーします。テスト フレームワークがスーパークラス メソッドの評価を完了すると、runSession
は、補助メソッド printAssertionSummary
(補助メソッドの定義を参照) を呼び出すことによりアサーション カウントの概要を表示します。フレームワークはこのメソッドをクライアント上で 1 回評価します。
methods (Access = protected) function runSession(plugin,pluginData) suiteSize = numel(pluginData.TestSuite); fprintf("## Running a total of %d tests\n\n",suiteSize) plugin.FinalizedNumPassingAssertions = 0; plugin.FinalizedNumFailingAssertions = 0; runSession@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData) fprintf("## Done running tests\n") plugin.printAssertionSummary end end
共有テスト フィクスチャとテスト ケースの作成の拡張
アサーションをカウントするためにイベント AssertionPassed
および AssertionFailed
にリスナーを追加します。これらのリスナーを追加するには、テスト フレームワークで使用するメソッドを拡張してテスト内容を作成します。テスト内容には、Test
要素ごとの TestCase
インスタンス、TestClassSetup
および TestClassTeardown
の methods
ブロックに対するクラス レベルの TestCase
インスタンス、および TestCase
クラスが属性 SharedTestFixtures
をもつ場合に使用する Fixture
インスタンスが含まれます。protected
アクセスが指定された methods
ブロックにこれらの作成メソッドを追加します。
作成メソッドをオーバーライドする際に、対応するスーパークラスを呼び出します。作成メソッドは、テスト フレームワークがそれぞれのコンテキストに対して作成する内容を返します。これらの各メソッドを incrementPassingAssertionsCount
および incrementFailingAssertionsCount
補助メソッドを使用して実装する場合、プラグインで必要なリスナーを、返された Fixture
または TestCase
インスタンスに追加します。
methods (Access = protected) function fixture = createSharedTestFixture(plugin,pluginData) fixture = createSharedTestFixture@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); fixture.addlistener("AssertionPassed", ... @(~,~)plugin.incrementPassingAssertionsCount); fixture.addlistener("AssertionFailed", ... @(~,~)plugin.incrementFailingAssertionsCount); end function testCase = createTestClassInstance(plugin,pluginData) testCase = createTestClassInstance@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); testCase.addlistener("AssertionPassed", ... @(~,~)plugin.incrementPassingAssertionsCount); testCase.addlistener("AssertionFailed", ... @(~,~)plugin.incrementFailingAssertionsCount); end function testCase = createTestMethodInstance(plugin,pluginData) testCase = createTestMethodInstance@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); testCase.addlistener("AssertionPassed", ... @(~,~)plugin.incrementPassingAssertionsCount); testCase.addlistener("AssertionFailed", ... @(~,~)plugin.incrementFailingAssertionsCount); end end
テスト スイートの一部の実行の拡張
テスト フレームワークは配列 TestSuite
全体をグループに分割し、それらをワーカーに割り当てて処理します。各ワーカーは、テスト スイートの部分を 1 つ以上実行できます。ワーカーの動作をカスタマイズするには、protected
アクセスが指定された methods
ブロック内で runTestSuite
メソッドをオーバーライドします。
テスト ランナーを拡張し、ワーカーが実行する各テスト グループの識別子を、グループ内の Test
要素数とともに表示します。さらに、パスと失敗のアサーション数を通信バッファーに格納し、確定した結果を生成するためにクライアントでこれらの値を取得できるようにします。すべてのプラグイン メソッドと同様に、runTestSuite
メソッドでは対応するスーパークラス メソッドを適切な時点で呼び出す必要があります。この場合は、プロパティの初期化後かつワーカー データの保存前に、スーパークラス メソッドを呼び出します。テスト フレームワークは、ワーカーの runTestSuite
をテスト スイートの部分の数と同数回評価します。
methods (Access = protected) function runTestSuite(plugin,pluginData) suiteSize = numel(pluginData.TestSuite); groupNumber = pluginData.Group; fprintf("### Running a total of %d tests in group %d\n", ... suiteSize,groupNumber) plugin.NumPassingAssertions = 0; plugin.NumFailingAssertions = 0; runTestSuite@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData) assertionStruct = struct( ... "Passing",plugin.NumPassingAssertions, ... "Failing",plugin.NumFailingAssertions); plugin.storeIn(pluginData.CommunicationBuffer,assertionStruct) end end
テスト特有のデータを保存するため、runTestSuite
の実装には Parallelizable
インターフェイスの storeIn
メソッドの呼び出しが含まれています。ワーカーがクライアントにレポートしなければならない場合は、storeIn
を retrieveFrom
とともに使用します。この例では、スーパークラス メソッドから戻った後、NumPassingAssertions
と NumFailingAssertions
にはテストのグループに対応するパスと失敗のアサーション数が含まれています。storeIn
はワーカー データを唯一の入力引数として受け入れるため、構造体 assertionStruct
は 2 つのフィールドを使用してアサーションのカウント数をグループ化します。
テスト スイートの確定部分のレポートの拡張
reportFinalizedSuite
を拡張して、テスト スイートの確定した各部分のテスト データを取得することにより、アサーションのカウント数を集計します。テスト スイートの部分の保存された構造体を取得するには、reportFinalizedSuite
のスコープ内で retrieveFrom
メソッドを呼び出します。致命的なアサーション エラーによっていずれのワーカーもバッファーに書き込めない場合など、バッファーが空の場合に既定のデータを返すには (R2024a 以降)、retrieveFrom
メソッドを呼び出すときに DefaultData
を指定します。フィールドの値を対応するクラス プロパティに追加し、スーパークラス メソッドを呼び出します。テスト フレームワークは、クライアント上でこのメソッドをテスト スイートの部分の数と同数回評価します。
methods (Access = protected) function reportFinalizedSuite(plugin,pluginData) assertionStruct = plugin.retrieveFrom( ... pluginData.CommunicationBuffer, ... DefaultData=struct("Passing",0,"Failing",0)); plugin.FinalizedNumPassingAssertions = ... plugin.FinalizedNumPassingAssertions + assertionStruct.Passing; plugin.FinalizedNumFailingAssertions = ... plugin.FinalizedNumFailingAssertions + assertionStruct.Failing; reportFinalizedSuite@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData) end end
補助メソッドの定義
private
アクセスが指定された methods
ブロックで、3 つの補助メソッドを定義します。これらのメソッドは、実行中のテスト スイートの各部分内でパスまたは失敗のアサーション数をインクリメントし、アサーション カウントの概要を出力します。
methods (Access = private) function incrementPassingAssertionsCount(plugin) plugin.NumPassingAssertions = plugin.NumPassingAssertions + 1; end function incrementFailingAssertionsCount(plugin) plugin.NumFailingAssertions = plugin.NumFailingAssertions + 1; end function printAssertionSummary(plugin) fprintf("%s\n",repmat('_',1,30)) fprintf("Total Assertions: %d\n", ... plugin.FinalizedNumPassingAssertions + ... plugin.FinalizedNumFailingAssertions) fprintf("\t%d Passed, %d Failed\n", ... plugin.FinalizedNumPassingAssertions, ... plugin.FinalizedNumFailingAssertions) end end
プラグイン クラス定義
以下のコードは、AssertionCountingPlugin
クラスの内容全体を示しています。
classdef AssertionCountingPlugin < ... matlab.unittest.plugins.TestRunnerPlugin & ... matlab.unittest.plugins.Parallelizable properties (SetAccess = private) NumPassingAssertions NumFailingAssertions FinalizedNumPassingAssertions FinalizedNumFailingAssertions end methods (Access = protected) function runSession(plugin,pluginData) suiteSize = numel(pluginData.TestSuite); fprintf("## Running a total of %d tests\n\n",suiteSize) plugin.FinalizedNumPassingAssertions = 0; plugin.FinalizedNumFailingAssertions = 0; runSession@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData) fprintf("## Done running tests\n") plugin.printAssertionSummary end function fixture = createSharedTestFixture(plugin,pluginData) fixture = createSharedTestFixture@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); fixture.addlistener("AssertionPassed", ... @(~,~)plugin.incrementPassingAssertionsCount); fixture.addlistener("AssertionFailed", ... @(~,~)plugin.incrementFailingAssertionsCount); end function testCase = createTestClassInstance(plugin,pluginData) testCase = createTestClassInstance@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); testCase.addlistener("AssertionPassed", ... @(~,~)plugin.incrementPassingAssertionsCount); testCase.addlistener("AssertionFailed", ... @(~,~)plugin.incrementFailingAssertionsCount); end function testCase = createTestMethodInstance(plugin,pluginData) testCase = createTestMethodInstance@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); testCase.addlistener("AssertionPassed", ... @(~,~)plugin.incrementPassingAssertionsCount); testCase.addlistener("AssertionFailed", ... @(~,~)plugin.incrementFailingAssertionsCount); end function runTestSuite(plugin,pluginData) suiteSize = numel(pluginData.TestSuite); groupNumber = pluginData.Group; fprintf("### Running a total of %d tests in group %d\n", ... suiteSize,groupNumber) plugin.NumPassingAssertions = 0; plugin.NumFailingAssertions = 0; runTestSuite@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData) assertionStruct = struct( ... "Passing",plugin.NumPassingAssertions, ... "Failing",plugin.NumFailingAssertions); plugin.storeIn(pluginData.CommunicationBuffer,assertionStruct) end function reportFinalizedSuite(plugin,pluginData) assertionStruct = plugin.retrieveFrom( ... pluginData.CommunicationBuffer, ... DefaultData=struct("Passing",0,"Failing",0)); plugin.FinalizedNumPassingAssertions = ... plugin.FinalizedNumPassingAssertions + assertionStruct.Passing; plugin.FinalizedNumFailingAssertions = ... plugin.FinalizedNumFailingAssertions + assertionStruct.Failing; reportFinalizedSuite@ ... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData) end end methods (Access = private) function incrementPassingAssertionsCount(plugin) plugin.NumPassingAssertions = plugin.NumPassingAssertions + 1; end function incrementFailingAssertionsCount(plugin) plugin.NumFailingAssertions = plugin.NumFailingAssertions + 1; end function printAssertionSummary(plugin) fprintf("%s\n",repmat('_',1,30)) fprintf("Total Assertions: %d\n", ... plugin.FinalizedNumPassingAssertions + ... plugin.FinalizedNumFailingAssertions) fprintf("\t%d Passed, %d Failed\n", ... plugin.FinalizedNumPassingAssertions, ... plugin.FinalizedNumFailingAssertions) end end end
テスト クラスの作成
現在のフォルダー内の ExampleTest.m
という名前のファイルで、パラメーター化されたテスト クラス ExampleTest
を作成します。このクラスには 300 個のテストが含まれ、そのうち 100 個は 1 ~ 10 の整数の疑似乱数を比較するアサーションになります。
classdef ExampleTest < matlab.unittest.TestCase properties (TestParameter) num1 = repmat({@()randi(10)},1,10) num2 = repmat({@()randi(10)},1,10) end methods (Test) function testAssert(testCase,num1,num2) testCase.assertNotEqual(num1(),num2()) end function testVerify(testCase,num1,num2) testCase.verifyNotEqual(num1(),num2()) end function testAssume(testCase,num1,num2) testCase.assumeNotEqual(num1(),num2()) end end end
テスト ランナーへのプラグインの追加およびテストの実行
ExampleTest
クラスからテスト スイートを作成します。
suite = testsuite("ExampleTest");
プラグインなしでテスト ランナーを作成します。次のコードで、出力を生成しないサイレント ランナーを作成します。
runner = testrunner("minimal");
次に、任意のプラグインを選択して追加できます。AssertionCountingPlugin
クラスのインスタンスをランナーに追加して、テストを並列で実行します。(ランナーで run
メソッドを呼び出すと、同じテストを逐次モードで実行することもできます。)
runner.addPlugin(AssertionCountingPlugin) runner.runInParallel(suite);
## Running a total of 300 tests Split tests into 18 groups and running them on 6 workers. ---------------- Finished Group 1 ---------------- ### Running a total of 20 tests in group 1 ---------------- Finished Group 2 ---------------- ### Running a total of 20 tests in group 2 ---------------- Finished Group 3 ---------------- ### Running a total of 19 tests in group 3 ---------------- Finished Group 4 ---------------- ### Running a total of 19 tests in group 4 ---------------- Finished Group 5 ---------------- ### Running a total of 18 tests in group 5 ---------------- Finished Group 6 ---------------- ### Running a total of 18 tests in group 6 ---------------- Finished Group 7 ---------------- ### Running a total of 18 tests in group 7 ---------------- Finished Group 8 ---------------- ### Running a total of 17 tests in group 8 ---------------- Finished Group 9 ---------------- ### Running a total of 17 tests in group 9 ----------------- Finished Group 10 ----------------- ### Running a total of 17 tests in group 10 ----------------- Finished Group 11 ----------------- ### Running a total of 16 tests in group 11 ----------------- Finished Group 12 ----------------- ### Running a total of 16 tests in group 12 ----------------- Finished Group 13 ----------------- ### Running a total of 15 tests in group 13 ----------------- Finished Group 14 ----------------- ### Running a total of 15 tests in group 14 ----------------- Finished Group 16 ----------------- ### Running a total of 14 tests in group 16 ----------------- Finished Group 15 ----------------- ### Running a total of 15 tests in group 15 ----------------- Finished Group 17 ----------------- ### Running a total of 14 tests in group 17 ----------------- Finished Group 18 ----------------- ### Running a total of 12 tests in group 18 ## Done running tests ______________________________ Total Assertions: 100 88 Passed, 12 Failed
参考
関数
クラス
matlab.unittest.plugins.TestRunnerPlugin
|matlab.unittest.plugins.Parallelizable
|matlab.unittest.TestRunner
|matlab.unittest.TestSuite
|matlab.unittest.TestCase
|matlab.unittest.fixtures.Fixture