Testing your application
The functionality described in this chapter is about testing your MATLAB or Python applications. The descriptions here are based on the functionality in MATLAB. The functionality in Python is mostly the same, so only significant differences are described here.
In addition to the tests you write for your application, it is recommended to write tests for the connection between your application and the front-end. For example, you could test whether clicking a certain button updates the submission data of another component using the data that was entered in the form.
In MATLAB, Simian GUI provides a testing framework that works similar to the MATLAB App Testing Framework. For Python the testing functionality can be used with the testing frameworks like unittest or pytest.
There are three gestures you can simulate during the tests:
choose
: Choose an option of multiple possibilities. For example, selecting one of multiple radio buttons.press
: Pressing a button, checkbox etc.type
: Type text in a component, for example in a TextField or Number component.
The table below shows you what gestures are available for what components. If a component is not listed in the table, no gestures are available for it.
Note: this testing framework does not create an actual instance of your application. Instead, the form object tree of the form being tested is created using the guiInit
method during the setup of the test method.
In MATLAB this is done in a TestMethodSetup method.
In Python a pytest fixture (with scope 'function' and autouse set to True
) creates the form object tree if the form is on the path.
If you are using a testing framework other than pytest, call the _initialize()
method of the Testing class in your test method setup code to get the same behaviour.
The submission data is updated when one of the gestures is executed. When a button is pressed using press
, the underlying event is triggered (guiEvent
).
Component | choose | press | type | Comment |
---|---|---|---|---|
Button | ✓ | |||
Checkbox | ✓ | ✓ | choose : Provide the target value (true/false).press : Toggles the checkbox. | |
Currency | ✓ | |||
DataGrid | Perform a gesture on a child component by providing this component as a parent. For example: testCase.type("textfield_key", "Text to type", "Parent", "my_datagrid"); | |||
Day | ✓ | |||
EditGrid | Perform a gesture on a child component by providing this component as a parent. For example: testCase.type("textfield_key", "Text to type", "Parent", "my_editgrid"); | |||
✓ | ||||
Number | ✓ | The value can be numerical or a string that is convertible to a number. | ||
Password | ✓ | |||
PhoneNumber | ✓ | The value to type must be a string. | ||
Radio | ✓ | The option to choose can be either the label or the value. | ||
Select | ✓ | The option to choose can be either the label or the value. | ||
Selectboxes | ✓ | ✓ | choose : testCase.choose(key, true/false, "Label", optionLabel) press : testCase.press(key, optionLabel) | |
Survey | ✓ | Syntax: testCase.choose(key, value, "Question", question) where value can be the label or the value of the answer and question can be the label or value of the question to answer. | ||
Tags | ✓ | Enter tags one by one with multiple gestures. | ||
TextArea | ✓ | |||
TextField | ✓ | |||
Time | ✓ | The value to type must be a string. |
In addition to these gestures, you can use the following methods:
Name | Syntax | Description |
---|---|---|
getSubmissionData | [data, isFound] = testCase.getSubmissionData(key, options) | Return the submission data for the component with the given key. Optional name-value pairs are:
|
verifySubmissionData | testCase.verifySubmissionData(key, expected, message, options) | Verify that the submission data for the component with the given key equals the expected value. When the values are not equal, the optional message is added to the diagnostics of the test. This takes the same optional input arguments as the getSubmissionData method above. |
Workflow
Consider the following MATLAB form (a Python form would be very similar) where two numbers and an operation can be selected. By clicking the Calculate button, the calculation is performed.
function payload = guiInit(metaData)
form = Form();
payload.form = form;
numberOne = component.Number("number_one", form);
numberOne.label = "First number";
numberOne.defaultValue = 0;
numberTwo = component.Number("number_two", form);
numberTwo.label = "Second number";
numberTwo.defaultValue = 0;
operation = component.Radio("radio_operation", form);
operation.label = "Operation";
operation.inline = true;
operation.setValues(["Add", "Subtract", "Multiply"], ["plus", "minus", "times"]);
calculateButton = component.Button("calculate_button", form);
calculateButton.label = "Calculate";
calculateButton.setEvent("Calculate");
numberThree = component.Number("number_three", form);
numberThree.label = "Answer";
numberThree.disabled = true;
end
The resulting form looks as follows:
The MATLAB guiEvent
function as shown below performs the calculations and puts the answer in the bottom Answer component:
function payload = guiEvent(metaData, payload)
numOne = getSubmissionData(payload, "number_one");
numTwo = getSubmissionData(payload, "number_two");
operation = getSubmissionData(payload, "radio_operation");
switch operation
case "plus"
answer = numOne + numTwo;
case "minus"
answer = numOne - numTwo;
case "times"
answer = numOne * numTwo;
otherwise
error("Unknown operation '%s'.", operation)
end
payload = setSubmissionData(payload, "number_three", answer);
end
Testing in MATLAB
This application can be tested in MATLAB as follows: Create a class that inherits from Testing
.
In turn, that class inherits from matlab.unittest.TestCase
,
so all testing-related functionality will be available. Your class must implement a property Namespace
that has no attributes and assign a default (string) value to it.
This is the namespace of the application, the same one you use for initializing the application in local MATLAB.
classdef testCalculator < Testing
properties
Namespace = "myprograms.calculator"
end
methods (Test)
end
end
Create a test method to test whether the multiplication of the example is properly executed. Enter values using the type
method, choose the operation with choose
and press the button using the press
method.
Verify that the value of the third Number component is correctly set after pressing the button.
classdef testExample < Testing
properties
Namespace = "myprogram.calculator"
end
methods (Test)
function testMultiplication(testCase)
% Test whether multiplication is properly executed.
testCase.type("number_one", 3);
testCase.type("number_two", 8);
testCase.choose("radio_operator", "Multiply");
testCase.press("button_calculate");
testCase.verifySubmissionData("number_three", 24, "Multiplication failed");
end
end
end
Testing in Python
The calculator form above can be tested in Python as follows: Create a class that inherits from testing.Testing
.
Your class must implement a property namespace
that contains the namespace of your form. After this you can start defining test methods using the methods described above.
For the above calculator form we can create a test method to test whether the multiplication of the example is properly executed.
Let us enter some values using the type
method, choose the operation with choose
and press the calculate button using the press
method.
After that we can verify whether the value of the third Number component is set to the value we are expecting.
import testing.Testing
class testExample(testing.Testing):
namespace = "myprogram.calculator"
def test_multiplication(self):
"""Test whether multiplication is properly executed."""
self.type("number_one", 3)
self.type("number_two", 8)
self.choose("radio_operator", "Multiply")
self.press("button_calculate")
self.verifySubmissionData("number_three", 24, "Multiplication failed")