Hi Cristian,
Thanks for raising this question. This is a common requirement which applies to anyone who is writing tests for an app that uses one of the modal operating system dialogs you mentioned. One way to approach this is to combine the App Testing Framework with the Mocking Framework. The latter allows you to mock the behavior of the dialog by returning the file or folder you need for test purposes.
In this situation, we need to be able to interchange the real function (when the app is running normally) and the mock function (when the app is being tested). To test standalone functions within the Mocking Framework, we need to first implement them as methods of a class.
Here is a step-by-step guide illustrating the workflow for implementing a test for an app making use of uigetfile. The full code is also attached.
Step 1
Start by creating an abstract superclass FileSelector with a uigetfile static method. We make this method static because it represents a standalone function.
classdef ( Abstract ) FileSelector
methods ( Static, Abstract )
varargout = uigetfile( varargin )
Step 2
Implement the standard uigetfile behavior in a subclass DefaultFileSelector of FileSelector that you can use whilst the app is running under normal conditions.
classdef DefaultFileSelector < FileSelector
function filename = uigetfile( varargin )
[file, path] = uigetfile( varargin{:} );
filename = fullfile( path, file );
Step 3
Modify the app to store a FileSelector object as one of its properties. In this example, we're using an App Designer app named FileSelectorApp.
classdef FileSelectorApp < matlab.apps.AppBase
properties (Access = ?matlab.unittest.TestCase)
FileSelector(1, 1) FileSelector = DefaultFileSelector
Modify the appropriate app callback(s) to use the uigetfile static method of the DefaultFileSelector class instead of the standalone uigetfile function.
function onSelectFileButtonPushed(app, event)
filepath = app.FileSelector.uigetfile();
Step 4
Implement the required tests. Start by deriving the test class from matlab.uitest.TestCase (to enable automated app testing) and matlab.mock.TestCase (to enable mocking).
During the test, we create a mock FileSelector object (mockFileSelector) and define how its uigetfile method behaves via the behavior object. The Mocking Framework allows you to define different types of behavior dynamically during the test process, which means you don't need to maintain separate code for multiple test cases.
In this example, we return a fixed filename MyFile.txt whenever uigetfile is called with any input signature.
Next, we inject the mock FileSelector into our running app, ensuring that when the test completes the usual uigetfile behavior is restored.
Finally, we use the App Testing Framework to operate the controls on the app that cause uigetfile to be called, and then verify the required behavior.
classdef tFileSelectorApp < matlab.uitest.TestCase & matlab.mock.TestCase
function tSelectingFileUpdatesLabel( testCase )
testCase.addTeardown( @() delete( app ) )
[mockFileSelector, behavior] = ...
testCase.createMock( ?FileSelector );
testFilename = "MyFile.txt";
when( withAnyInputs( behavior.uigetfile() ), ...
matlab.mock.actions.AssignOutputs( testFilename ) )
app.FileSelector = mockFileSelector;
testCase.addTeardown( @() revertFileSelector() )
testCase.press( app.SelectFileButton )
testCase.verifyEqual( string( app.SelectedFileLabel.Text ), ...
testFilename, "Selecting the file " + testFilename + ...
" did not update the label text to " + testFilename + "." )
function revertFileSelector()
app.FileSelector = DefaultFileSelector();
Reference:
Best wishes,
Ken