アプリ テスト フレームワークとモッキング フレームワークを使用するテストの記述
この例では、アプリ テスト フレームワークとモッキング フレームワークを使用するテストの記述方法を示します。アプリには、ファイル選択のダイアログ ボックスと、選択したファイルを示すラベルが含まれています。アプリをプログラムによりテストするには、モック オブジェクトを使用してファイル セレクターの動作を定義します。
アプリの作成
現在の作業フォルダー内に launchApp
アプリを作成します。ユーザーはこのアプリを使って入力ファイルを選択し、そのファイルの名前をアプリに表示できます。ファイル選択のダイアログ ボックスは、ユーザー入力を待機するブロッキング モーダル ダイアログ ボックスです。
function app = launchApp f = uifigure; button = uibutton(f,'Text','Input file'); button.ButtonPushedFcn = @(src,evt)pickFile; label = uilabel(f,'Text','No file selected'); label.Position(1) = button.Position(1) + button.Position(3) + 25; label.Position(3) = 200; % Add components to an App struct for output app.UIFigure = f; app.Button = button; app.Label = label; function file = pickFile() [file,folder,status] = uigetfile('*.*'); if status label.Text = file; end end end
テストの前にこのアプリのプロパティを確認するため、コマンド プロンプトでアプリのインスタンスを作成します。この手順はテストには必要ありませんが、アプリ テストで使用されるプロパティを確認しておくと役に立ちます。たとえば、アプリ オブジェクト内の [Input file] ボタンにアクセスするには、app.Button
を使用します。
app = launchApp;
手動操作を伴うアプリのテスト
モックを使用しないで LaunchAppTest
クラスを作成します。このテストでは、input2.txt
ファイルが現在の作業フォルダー内に存在すると仮定します。これが存在しない場合は作成してください。テストでは、[Input file] ボタンをプログラムによりクリックして、ラベルが 'input2.txt'
に一致することを検証します。手動でファイルを選択しなければなりません。
classdef LaunchAppTest < matlab.uitest.TestCase properties TestFile = 'input2.txt'; end methods(TestClassSetup) function checkTestFiles(tc) import matlab.unittest.constraints.IsFile tc.assumeThat(tc.TestFile,IsFile) end end methods (Test) function testInputButton(tc) app = launchApp; tc.addTeardown(@close,app.UIFigure); tc.press(app.Button); tc.verifyEqual(app.Label.Text,tc.TestFile) end end end
テストを実行します。ファイル選択のダイアログ ボックスが表示されたら、input2.txt
を選択して MATLAB がテストを続行できるようにします。それ以外のファイルを選択した場合はテストが失敗します。
results = runtests('LaunchAppTest');
Running LaunchAppTest . Done LaunchAppTest __________
完全に自動化されたテストの作成
手動操作なしでアプリをテストするには、モッキング フレームワークを使用します。ファイル選択サービスをアプリに実装するのではなく、サービスを受け入れるようにアプリを変更します ("依存関係の挿入")。
ファイル選択機能を実装する FileChooser
サービスを Abstract
メソッドで作成します。
classdef FileChooser % Interface to choose a file methods (Abstract) [file,folder,status] = chooseFile(chooser,varargin) end end
ファイルの選択に関数 uigetfile
を使用する、既定の FileChooser
を作成します。
classdef DefaultFileChooser < FileChooser methods function [file,folder,status] = chooseFile(chooser,varargin) [file,folder,status] = uigetfile(varargin{:}); end end end
オプションの FileChooser
オブジェクトを受け入れるようにアプリを変更します。入力なしで呼び出された場合、アプリは DefaultFileChooser
のインスタンスを使用します。
function app = launchApp(fileChooser) if nargin==0 fileChooser = DefaultFileChooser; end f = uifigure; button = uibutton(f,'Text','Input file'); button.ButtonPushedFcn = @(src,evt)pickFile(fileChooser); label = uilabel(f,'Text','No file selected'); label.Position(1) = button.Position(1) + button.Position(3) + 25; label.Position(3) = 200; % Add components to an App struct for output app.UIFigure = f; app.Button = button; app.Label = label; function file = pickFile(fileChooser) [file,folder,status] = fileChooser.chooseFile('*.*'); if status label.Text = file; end end end
LaunchAppTest
に以下の変更を行います。
matlab.uitest.TestCase
とmatlab.mock.TestCase
の両方から継承するようにテストを変更します。properties
ブロックとTestClassSetup
ブロックを削除します。モックがchooseFile
メソッド呼び出しの出力を定義するので、テストは外部ファイルの存在に依存しません。以下を実行するように
testInputButton
テスト メソッドを変更します。FileChooser
のモック オブジェクトを作成する。chooseFile
メソッドが入力'*.*'
で呼び出された場合の出力が、テスト ファイルの名前 ('input2.txt'
)、現在の作業フォルダー、および選択されたフィルター インデックス 1 になるように、モック動作を定義する。これらの出力は、関数uigetfile
からの出力と類似しています。ボタンをクリックして選択されたファイル名を検証する。これらの手順は元のテストと同じですが、モックによって出力値が割り当てられるので、テストを続行するためにアプリを手動で操作する必要はありません。
[Cancel] ボタンをテストするため、テスト メソッド
testInputButton_Cancel
を追加して、以下が実行されるようにします。FileChooser
のモック オブジェクトを作成する。chooseFile
メソッドが入力'*.*'
で呼び出された場合の出力が、テスト ファイルの名前 ('input2.txt'
)、現在の作業フォルダー、および選択されたフィルター インデックス 0 になるように、モック動作を定義する。これらの出力は、ユーザーがファイルを選択してからキャンセルを選択した場合の関数uigetfile
からの出力と類似しています。ボタンをクリックし、テストが
chooseFile
メソッドを呼び出すこと、およびファイルが選択されなかったことをラベルが示すことを検証する。
classdef LaunchAppTest < matlab.uitest.TestCase & matlab.mock.TestCase methods (Test) function testInputButton(tc) import matlab.mock.actions.AssignOutputs fname = 'myFile.txt'; [mockChooser,behavior] = tc.createMock(?FileChooser); when(behavior.chooseFile('*.*'),AssignOutputs(fname,pwd,1)) app = launchApp(mockChooser); tc.addTeardown(@close,app.UIFigure); tc.press(app.Button); tc.verifyEqual(app.Label.Text,fname); end function testInputButton_Cancel(tc) import matlab.mock.actions.AssignOutputs [mockChooser, behavior] = tc.createMock(?FileChooser); when(behavior.chooseFile('*.*'),AssignOutputs('myFile.txt',pwd,0)) app = launchApp(mockChooser); tc.addTeardown(@close,app.UIFigure); tc.press(app.Button); tc.verifyCalled(behavior.chooseFile('*.*')); tc.verifyEqual(app.Label.Text,'No file selected'); end end end
テストを実行します。テストは、ファイルの手動選択なしで最後まで実行されます。
results = runtests('LaunchAppTest');
Running LaunchAppTest .. Done LaunchAppTest __________
参考
matlab.mock.TestCase
| matlab.uitest.TestCase