Main Content

アプリ テスト フレームワークとモッキング フレームワークを使用するテストの記述

この例では、アプリ テスト フレームワークとモッキング フレームワークを使用するテストの記述方法を示します。アプリには、ファイル選択のダイアログ ボックスと、選択したファイルを示すラベルが含まれています。アプリをプログラムによりテストするには、モック オブジェクトを使用してファイル セレクターの動作を定義します。

アプリの作成

現在の作業フォルダー内に 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;

App window displaying Input file button

手動操作を伴うアプリのテスト

モックを使用しないで 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.TestCasematlab.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
__________

参考

|

関連するトピック