テスト結果にデータを追加するプラグインの作成
この例では、TestResult
オブジェクトにデータを追加するプラグインの作成方法を説明します。このプラグインは、アサーション内の実際の値と期待値を、TestResult
オブジェクトの Details
プロパティに追加します。TestRunner
を拡張するため、プラグインは matlab.unittest.plugins.TestRunnerPlugin
クラスの特定メソッドをオーバーライドします。
プラグイン クラスの作成
現在のフォルダー内のファイルに、TestRunnerPlugin
クラスから継承するカスタム プラグイン クラス DetailsRecordingPlugin
を作成します。DetailsRecordingPlugin
の完全なコードは、DetailsRecordingPlugin クラス定義の概要を参照してください。
実際の値と期待値を TestResult
オブジェクトに保存するには、2 つの定数プロパティ ActField
および ExpField
を、properties
ブロック内で定義します。ActField
の値を、実際の値を含む Details
構造体のフィールド名に設定します。ExpField
の値を、期待値を含むフィールドの名前に設定します。
properties (Constant, Access = private) ActField = 'ActualValue'; ExpField = 'ExpectedValue'; end
Details プロパティへのフィールドの追加
テスト セッションに属するすべての TestResult
オブジェクトの Details
プロパティに新しいフィールドを追加するには、protected
アクセスをもつ methods
ブロック内にある TestRunnerPlugin
の runSession
メソッドをオーバーライドします。runSession
は、TestResult
オブジェクトの Details
構造体に対して空のフィールドを 2 つ追加し、テスト実行全体をトリガーするスーパークラス メソッドを呼び出します。
methods (Access = protected) function runSession(plugin,pluginData) resultDetails = pluginData.ResultDetails; resultDetails.append(plugin.ActField,{}) resultDetails.append(plugin.ExpField,{}) runSession@matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); end end
フィールドを追加するために、runSession
の実装には、matlab.unittest.plugins.plugindata.ResultDetails
クラスの append
メソッドに対する呼び出しが含まれます。呼び出しごとに、空のフィールドが Details
構造体に追加されます。
共有テスト フィクスチャと TestCase インスタンスの作成の拡張
テスト フレームワークで使用するメソッドを拡張してテスト内容を作成することにより、AssertionPassed
イベントおよび AssertionFailed
イベントのリスナーを追加します。テスト内容には、Test
要素ごとの TestCase
インスタンス、TestClassSetup
および TestClassTeardown
メソッド ブロックに対するクラス レベルの TestCase
インスタンス、および TestCase
クラスが属性 SharedTestFixtures
をもつ場合に使用する Fixture
インスタンスが含まれます。
作成メソッドをオーバーライドする際に、対応するスーパークラスを呼び出します。返される Fixture
インスタンスまたは TestCase
インスタンスに追加するリスナーにより、アサーションが実行されるたびに reactToAssertion
補助メソッドが実行されます。テスト結果にアサーション データを追加するには、結果修飾子インスタンスを、アサーション イベント リスナーのデータと共に、補助メソッドに渡します。
protected
アクセスが指定された methods
ブロックにこれらの作成メソッドを追加します。
methods (Access = protected) function fixture = createSharedTestFixture(plugin, pluginData) fixture = createSharedTestFixture@... matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData); resultDetails = pluginData.ResultDetails; fixture.addlistener('AssertionPassed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); fixture.addlistener('AssertionFailed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); end function testCase = createTestClassInstance(plugin,pluginData) testCase = createTestClassInstance@... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); resultDetails = pluginData.ResultDetails; testCase.addlistener('AssertionPassed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); testCase.addlistener('AssertionFailed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); end function testCase = createTestMethodInstance(plugin,pluginData) testCase = createTestMethodInstance@... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); resultDetails = pluginData.ResultDetails; testCase.addlistener('AssertionPassed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); testCase.addlistener('AssertionFailed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); end end
補助メソッドの定義
private
アクセスが指定された methods
ブロックで、補助メソッド reactToAssertion
を定義します。このメソッドは、QualificationEventData
インスタンスを使用してアサーション内の実際の値と期待値を IsEqualTo
制約に基づいて抽出し、抽出された値を cell 配列に変換し、その cell 配列を対応する TestResult
オブジェクトのフィールドに追加します。
methods (Access = private) function reactToAssertion(plugin,evd,resultDetails) if ~isa(evd.Constraint,'matlab.unittest.constraints.IsEqualTo') return end resultDetails.append(plugin.ActField,{evd.ActualValue}) resultDetails.append(plugin.ExpField,{evd.Constraint.Expected}) end end
DetailsRecordingPlugin クラス定義の概要
以下のコードは、DetailsRecordingPlugin
の完全な内容を提示します。
classdef DetailsRecordingPlugin < matlab.unittest.plugins.TestRunnerPlugin properties (Constant, Access = private) ActField = 'ActualValue'; ExpField = 'ExpectedValue'; end methods (Access = protected) function runSession(plugin,pluginData) resultDetails = pluginData.ResultDetails; resultDetails.append(plugin.ActField,{}) resultDetails.append(plugin.ExpField,{}) runSession@matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); end function fixture = createSharedTestFixture(plugin, pluginData) fixture = createSharedTestFixture@... matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData); resultDetails = pluginData.ResultDetails; fixture.addlistener('AssertionPassed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); fixture.addlistener('AssertionFailed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); end function testCase = createTestClassInstance(plugin,pluginData) testCase = createTestClassInstance@... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); resultDetails = pluginData.ResultDetails; testCase.addlistener('AssertionPassed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); testCase.addlistener('AssertionFailed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); end function testCase = createTestMethodInstance(plugin,pluginData) testCase = createTestMethodInstance@... matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData); resultDetails = pluginData.ResultDetails; testCase.addlistener('AssertionPassed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); testCase.addlistener('AssertionFailed',... @(~,evd)plugin.reactToAssertion(evd,resultDetails)); end end methods (Access = private) function reactToAssertion(plugin,evd,resultDetails) if ~isa(evd.Constraint,'matlab.unittest.constraints.IsEqualTo') return end resultDetails.append(plugin.ActField,{evd.ActualValue}) resultDetails.append(plugin.ExpField,{evd.Constraint.Expected}) end end end
サンプル テスト クラスの作成
現在のフォルダーに、以下のパラメーター化されたテスト クラスを含む ExampleTest.m
という名前のファイルを作成します。クラスは結果的に 25 個の要素をもつテスト スイートとなり、各要素は、乱数発生器の別々のシードを使用して実行されたそれぞれの実験に対応します。各実験で、テスト フレームワークは、正規分布した乱数の 1 行 100 列のベクトルを作成し、実際のサンプル平均と期待されるサンプル平均の差の大きさが 0.1 以内であることをアサートします。
classdef ExampleTest < matlab.unittest.TestCase properties SampleSize = 100; end properties (TestParameter) seed = num2cell(randi(10^6,1,25)); end methods(Test) function testMean(testCase,seed) import matlab.unittest.constraints.IsEqualTo import matlab.unittest.constraints.AbsoluteTolerance rng(seed) testCase.assertThat(mean(randn(1,testCase.SampleSize)),... IsEqualTo(0,'Within',AbsoluteTolerance(0.1))); end end end
TestRunner にプラグインを追加してテストを実行
コマンド プロンプトで ExampleTest
クラスからテスト スイートを作成します。
import matlab.unittest.TestSuite import matlab.unittest.TestRunner suite = TestSuite.fromClass(?ExampleTest);
プラグインなしで TestRunner
インスタンスを作成します。このコードはメッセージを表示しないランナーを作成し、インストールされたプラグインの制御を可能にします。
runner = TestRunner.withNoPlugins;
DetailsRecordingPlugin
をランナーに追加して、テストを実行します。
runner.addPlugin(DetailsRecordingPlugin) result = runner.run(suite)
result = 1×25 TestResult array with properties: Name Passed Failed Incomplete Duration Details Totals: 18 Passed, 7 Failed (rerun), 7 Incomplete. 0.12529 seconds testing time.
乱数発生の動作に関する詳細を取得するには、テスト結果の Details
構造体から構造体配列を作成します。
details = [result.Details]
details = 1×25 struct array with fields: ActualValue ExpectedValue
各テストでの実際の値と期待値の差を含む配列を作成し、誤差値を棒グラフで表示します。長さが 0.1 より大きい 7 本のバーは、失敗したテストに相当します。
errorInMean = cell2mat([details.ExpectedValue]) - cell2mat([details.ActualValue]); bar(errorInMean) xlabel('Experiment') ylabel('Error')
参考
matlab.unittest.plugins.TestRunnerPlugin
| matlab.unittest.TestRunner
| matlab.unittest.fixtures.Fixture
| matlab.unittest.TestSuite
| addlistener
| matlab.unittest.TestResult
| matlab.unittest.plugins.plugindata.ResultDetails