编写使用 App 测试和模拟框架的测试
此示例说明如何编写使用 App 测试框架和模拟框架的测试。该 App 包含一个文件选择对话框和一个指示所选文件的标签。要以编程方式测试该 App,请使用一个 mock 对象来定义文件选择器的行为。
创建 App
在您当前文件夹中创建 launchApp
。该 App 允许用户选择一个输入文件并在 App 中显示文件的名称。文件选择对话框是一个等待用户输入的阻断型模态对话框。
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
要在测试之前浏览 App 的属性,请在命令提示符下调用 launchApp
函数。此步骤对于测试不是必需的,但是了解 App 测试使用的属性会很有帮助。例如,使用 app.Button
访问 App 对象内的输入文件按钮。
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
在不使用仿件的情况下创建 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 __________
创建全自动测试
要测试 App 而无需手动干预,请使用模拟框架。将 App 修改为接受文件选择服务,而不是在 App 中实现该服务(依赖项注入)。
使用 Abstract
方法创建一个 FileChooser
服务,用于实现文件选择功能。
classdef FileChooser % Interface to choose a file methods (Abstract) [file,folder,status] = chooseFile(chooser,varargin) end end
创建一个默认 FileChooser
服务,它使用 uigetfile
函数进行文件选择。
classdef DefaultFileChooser < FileChooser methods function [file,folder,status] = chooseFile(~,varargin) [file,folder,status] = uigetfile(varargin{:}); end end end
将 App 更改为接受可选的 FileChooser
对象。当在没有输入的情况下调用时,该 App 使用 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.TestCase
和matlab.mock.TestCase
中继承。删除
properties
代码块和TestClassSetup
methods
代码块。由于 mock 定义chooseFile
方法调用的相应输出,因此测试不依赖于外部文件的存在。更改
testInput
方法以执行以下操作:从
FileChooser
创建一个 mock 对象。定义 mock 行为,以便在使用输入
"*.*"
调用chooseFile
方法时,输出为文件名 ('input.txt'
)、当前文件夹和选定的过滤器索引1
。这些输出类似于uigetfile
函数的输出。使用
mockChooser
对象启动 App。按下按钮并验证所选文件的名称。这些操作与原始测试中的步骤相同,但 mock 会分配输出值,因此您无需与 App 交互即可继续测试。
要测试取消按钮,请添加名为
testCancel
的Test
方法来执行以下操作:从
FileChooser
创建一个 mock 对象。定义 mock 行为,以便在使用输入
"*.*"
调用chooseFile
方法时,输出为文件名 ('input.txt'
)、当前文件夹和选定的过滤器索引0
。这些输出类似于在用户选择一个文件然后选择取消时uigetfile
函数的输出。使用
mockChooser
对象启动 App。按下按钮并验证测试调用
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 __________