Main Content

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

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

アプリの作成

現在のフォルダー内に launchApp アプリを作成します。ユーザーはこのアプリを使って入力ファイルを選択し、そのファイルの名前をアプリに表示できます。ファイル選択のダイアログ ボックスは、ユーザー入力を待機するブロッキング モーダル ダイアログ ボックスです。

function app = launchApp
f = uifigure;
button = uibutton(f,"Text","Input file");
button.ButtonPushedFcn = @(src,event) 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 app
app.UIFigure = f;
app.Button = button;
app.Label = label;

    function file = pickFile
        [file,~,status] = uigetfile("*.*");
        if status
            label.Text = file;
        end
    end
end

テスト前にアプリのプロパティを調べるには、コマンド プロンプトで関数 launchApp を呼び出します。この手順はテストには必要ありませんが、アプリ テストで使用されるプロパティを確認しておくと役に立ちます。たとえば、アプリ内の [Input file] ボタンにアクセスするには、app.Button を使用します。

app = launchApp;
app.Button
ans = 

  Button (Input file) with properties:

               Text: 'Input file'
               Icon: ''
    ButtonPushedFcn: @(src,event)pickFile
           Position: [100 100 100 22]

  Show all properties

App window displaying the Input file button and the text "No file selected"

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

モックを使用しないで LaunchAppTest テスト クラスを作成します。このテストでは、input.txt ファイルが現在のフォルダー内に存在しなければなりません。これが存在しない場合は作成してください。テストでは、[Input file] ボタンをプログラムによりクリックして、ラベルが 'input.txt' に一致することを検証します。手動でファイルを選択しなければなりません。

classdef LaunchAppTest < matlab.uitest.TestCase
    properties
        Filename = 'input.txt'
    end
    methods(TestClassSetup)
        function checkFile(testCase)
            import matlab.unittest.constraints.IsFile
            testCase.assertThat(testCase.Filename,IsFile)
        end
    end
    methods (Test)
        function testInput(testCase)
            app = launchApp;
            testCase.addTeardown(@close,app.UIFigure)

            testCase.press(app.Button)

            testCase.verifyEqual(app.Label.Text,testCase.Filename)
        end
    end
end

テストを実行します。ファイル選択のダイアログ ボックスが表示されたら、input.txt を選択して MATLAB がテストを続行できるようにします。それ以外のファイルを選択した場合はテストが失敗します。

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(~,varargin)
            [file,folder,status] = uigetfile(varargin{:});
        end
    end
end

オプションの FileChooser オブジェクトを受け入れるようにアプリを変更します。入力なしで呼び出された場合、アプリは DefaultFileChooser のインスタンスを使用します。

function app = launchApp(fileChooser)
arguments
    fileChooser (1,1) FileChooser = DefaultFileChooser
end

f = uifigure;
button = uibutton(f,"Text","Input file");
button.ButtonPushedFcn = @(src,event) 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 app
app.UIFigure = f;
app.Button = button;
app.Label = label;

    function file = pickFile(fileChooser)
        [file,~,status] = fileChooser.chooseFile("*.*");
        if status
            label.Text = file;
        end
    end
end

LaunchAppTest に次の変更を加えます。

  • matlab.uitest.TestCasematlab.mock.TestCase の両方から継承するようにクラスを変更します。

  • properties ブロックと TestClassSetup methods ブロックを削除します。モックが chooseFile メソッド呼び出しの出力を定義するので、テストは外部ファイルの存在に依存しません。

  • 次のアクションを実行するように testInput メソッドを変更します。

    • FileChooser からモック オブジェクトを作成する。

    • chooseFile メソッドが入力 "*.*" で呼び出された場合の出力が、ファイル名 ('input.txt')、現在のフォルダー、および選択されたフィルター インデックス 1 になるように、モック動作を定義する。これらの出力は、関数 uigetfile からの出力と類似しています。

    • mockChooser オブジェクトを使用してアプリを起動する。

    • ボタンを押して選択されたファイルの名前を検証する。これらのアクションは元のテストと同じですが、モックによって出力値が割り当てられるので、テストを続行するためにアプリを手動で操作する必要はありません。

  • [Cancel] ボタンをテストするには、次のアクションを実行する testCancel という名前の Test メソッドを追加します。

    • FileChooser からモック オブジェクトを作成する。

    • chooseFile メソッドが入力 "*.*" で呼び出された場合の出力が、ファイル名 ('input.txt')、現在のフォルダー、および選択されたフィルター インデックス 0 になるように、モック動作を定義する。これらの出力は、ユーザーがファイルを選択してからキャンセルを選択した場合の関数 uigetfile からの出力と類似しています。

    • mockChooser オブジェクトを使用してアプリを起動する。

    • ボタンをクリックし、テストが chooseFile メソッドを呼び出すこと、およびファイルが選択されなかったことをラベルが示すことを検証する。

classdef LaunchAppTest < matlab.uitest.TestCase & matlab.mock.TestCase
    methods (Test)
        function testInput(testCase)
            import matlab.mock.actions.AssignOutputs
            filename = 'input.txt';

            [mockChooser,behavior] = testCase.createMock(?FileChooser);
            when(behavior.chooseFile("*.*"),AssignOutputs(filename,pwd,1))

            app = launchApp(mockChooser);
            testCase.addTeardown(@close,app.UIFigure)

            testCase.press(app.Button)

            testCase.verifyEqual(app.Label.Text,filename)
        end

        function testCancel(testCase)
            import matlab.mock.actions.AssignOutputs

            [mockChooser,behavior] = testCase.createMock(?FileChooser);
            when(behavior.chooseFile("*.*"),AssignOutputs('input.txt',pwd,0))

            app = launchApp(mockChooser);
            testCase.addTeardown(@close,app.UIFigure)

            testCase.press(app.Button)

            testCase.verifyCalled(behavior.chooseFile("*.*"))
            testCase.verifyEqual(app.Label.Text,'No file selected')
        end
    end
end

テストを実行します。テストは、ファイルの手動選択なしで最後まで実行されます。

runtests("LaunchAppTest");
Running LaunchAppTest
..
Done LaunchAppTest
__________

参考

クラス

関連するトピック