Main Content

matlab.test.behavior.Missing class

Package: matlab.test.behavior
Superclasses: matlab.unittest.TestCase

Test if class satisfies contract for missing values

Description

To test if the missing value for your class satisfies the missing contract in MATLAB®, create a test class that derives from the matlab.test.behavior.Missing class. If your class represents a data type and you want MATLAB to treat missing values of your class similar to built-in classes, ensure that your class satisfies the missing contract.

Typically, you use the behavior test as part of a test-driven development workflow. If you want the missing value for your class to satisfy the missing contract with MATLAB, write the behavior test and modify the class under test until the test results are as you expect. For example, if your class supports comparisons and ordering and is usable as a missing value indicator, all tests should pass. If your class does not support ordering, set the SupportsOrdering property to false and expect that MATLAB filters out tests associated with ordering.

Your behavior test only must derive from matlab.test.behavior.Missing and define the abstract properties. However, since matlab.test.behavior.Missing is a subclass of matlab.unittest.TestCase, you can use the functionality of the Unit Testing Framework.

Class Attributes

Abstract
true
HandleCompatible
true

For information on class attributes, see Class Attributes.

Properties

expand all

Define values for all abstract properties in the properties block of your test class.

Missing value for class under test, specified as a valid MATLAB scalar value or an expression that returns a non-missing value.

Example: NaN or missing or ' '

Attributes:

SetAccess
public
GetAccess
public
Abstract
true

Any non-missing value for the class under test, specified as a valid MATLAB scalar value or an expression that returns a non-missing value. Typically, if the class constructor returns a non-missing value, PrototypeValue is a call to the constructor.

Example: 0 or datetime

Attributes:

SetAccess
public
GetAccess
public
Abstract
true

List of classes that can be converted to the class under test, specified as a string array of class names.

If you can convert to the other class and then back to your class, then your class has a supported conversion from the other class. For example, if MyClass(OtherClass(missing)) == MyClass(missing) than OtherClass is a class with supported conversions.

Example: "string" or ["double","single"]

Attributes:

SetAccess
public
GetAccess
public
Abstract
true

Data Types: string

If necessary, redefine values for concrete properties in a function in the TestClassSetup methods block of your test class.

Indicator that the class supports comparison, specified as true or false. A class that supports comparisons allows use of == and ~=.

If you set SupportsComparison to false, expect comparison and ordering tests to be filtered by assumption failure. MATLAB does not run the tests.

Attributes:

SetAccess
protected
GetAccess
public

Data Types: logical

Indicator that the class supports ordering, specified as true or false. A class that supports ordering allows use of <, >, <=, and >=.

If you set SupportsOrdering to false, expect associated tests to be filtered by assumption failure. MATLAB does not run the tests.

Attributes:

SetAccess
protected
GetAccess
public

Data Types: logical

Indicator that the class is usable as a missing value indicator to the ismissing function, specified as true or false.

If you set UsableAsMissingIndicator to false, expect associated tests to be filtered by assumption failure. MATLAB does not run the tests.

Attributes:

SetAccess
protected
GetAccess
public

Data Types: logical

The fill value that your class uses for growing arrays, specified as a valid MATLAB scalar value. By default, the value of FillValue is the same as the value of the MissingValue property.

Example: 0

Attributes:

SetAccess
protected
GetAccess
public

Examples

collapse all

Create the MyDataClass class that can contain a missing value. The class supports comparison and ordering, and the missing value implementation should satisfy the missing contract in MATLAB. If you call the constructor with no inputs, it returns a missing value.

classdef MyDataClass
    properties
        SomeData;
        MissingVal = false;
    end
    
    methods
        function obj = MyDataClass(value)
            if nargin
                m = size(value,1);
                n = size(value,2);
                for i = 1:m
                    for j = 1:n
                        if ismissing(value(i,j))
                            obj(i,j).MissingVal = true;
                        else
                            obj(i,j).SomeData = value(i,j);
                            obj(i,j).MissingVal = false;
                        end
                    end
                end
            else
                obj.MissingVal = true;
            end
        end
        
        % Define ismissing behavior
        function m = ismissing(obj,v)
            if nargin > 1
                m = isequaln(obj,v);
            else
                m = [obj.MissingVal];
            end
            m = reshape(m,size(obj));
        end
    end
end

To create a simple test class that checks that MyDataClass satisfies the missing value contract, subclass matlab.test.behavior.Missing. The test can use the functionality of the unit testing framework, but MissingValueTest is checking the missing contract only.

classdef MissingValueTest < matlab.test.behavior.Missing
    properties
        MissingValue = MyDataClass;
        PrototypeValue = MyDataClass(7);
        ClassesWithSupportedConversions = [];
    end
end

Run the tests and review the results. The tests for comparison, ordering, equality, and using MyDataClass as the second input to ismissing fail.

results = runtests('MissingValueTest');
Running MissingValueTest
....
================================================================================
Error occurred in MissingValueTest/comparison and it did not run to completion.

    ---------
    Error ID:
    ---------
    'MATLAB:UndefinedFunction'

    --------------
    Error Details:
    --------------
    Undefined function 'eq' for input arguments of type 'MyDataClass'.
    
    Error in matlab.test.behavior.Missing/comparison (line 129)
                testCase.verifyFalse(testCase.MissingValue == testCase.MissingValue,
                getString(message('MATLAB:test:behavior:missing:EqualFalse')));
================================================================================
.
================================================================================
Error occurred in MissingValueTest/ordering and it did not run to completion.

    ---------
    Error ID:
    ---------
    'MATLAB:UndefinedFunction'

    --------------
    Error Details:
    --------------
    Undefined function 'lt' for input arguments of type 'MyDataClass'.
    
    Error in matlab.test.behavior.Missing/ordering (line 136)
                testCase.verifyFalse(testCase.MissingValue < testCase.MissingValue,
                getString(message('MATLAB:test:behavior:missing:LessThanFalse')));
================================================================================
.
================================================================================
Verification failed in MissingValueTest/isequalRules.

    ----------------
    Test Diagnostic:
    ----------------
    isequal(MissingValue, MissingValue) must return false, because all missing values are unequal.

    ---------------------
    Framework Diagnostic:
    ---------------------
    verifyFalse failed.
    --> The value must evaluate to "false".
    
    Actual Value:
      logical
    
       1

    ------------------
    Stack Information:
    ------------------
    In <matlabroot>\toolbox\matlab\datatypes\+matlab\+test\+behavior\Missing.m (Missing.isequalRules) at 145
================================================================================

================================================================================
Verification failed in MissingValueTest/isequalRules.

    ----------------
    Test Diagnostic:
    ----------------
    isequaln(MissingValue, missing) must return true.

    ---------------------
    Framework Diagnostic:
    ---------------------
    verifyTrue failed.
    --> The value must evaluate to "true".
    
    Actual Value:
      logical
    
       0

    ------------------
    Stack Information:
    ------------------
    In <matlabroot>\toolbox\matlab\datatypes\+matlab\+test\+behavior\Missing.m (Missing.isequalRules) at 147
================================================================================
.
================================================================================
Verification failed in MissingValueTest/IsMissing2ndInput.

    ----------------
    Test Diagnostic:
    ----------------
    ismissing(MissingValue, missing) must return true.

    ---------------------
    Framework Diagnostic:
    ---------------------
    verifyTrue failed.
    --> The value must evaluate to "true".
    
    Actual Value:
      logical
    
       0

    ------------------
    Stack Information:
    ------------------
    In <matlabroot>\toolbox\matlab\datatypes\+matlab\+test\+behavior\Missing.m (Missing.IsMissing2ndInput) at 154
================================================================================
...
Done MissingValueTest
__________

Failure Summary:

     Name                                Failed  Incomplete  Reason(s)
    =================================================================================
     MissingValueTest/comparison           X         X       Errored.
    ---------------------------------------------------------------------------------
     MissingValueTest/ordering             X         X       Errored.
    ---------------------------------------------------------------------------------
     MissingValueTest/isequalRules         X                 Failed by verification.
    ---------------------------------------------------------------------------------
     MissingValueTest/IsMissing2ndInput    X                 Failed by verification.

Iteratively update MyDataClass to satisfy the missing contract. To satisfy comparison and ordering, define eq, ne, lt, gt, le, and ge in the methods block of MyDataClass.

        % Class supports comparison
        function tf = eq(obj1,obj2)
            tf = ~any(ismissing([obj1 obj2])) && eq(obj1.SomeData,obj2.SomeData);
        end
        function tf = ne(obj1,obj2)
            tf = ~eq(obj1,obj2);
        end
        
        % Class supports ordering
        function tf = lt(obj1,obj2)
            tf = ~any(ismissing([obj1 obj2])) && lt(obj1.SomeData,obj2.SomeData);
        end
        function tf = gt(obj1,obj2)
            tf = lt(obj2,obj1);
        end   
        function tf = le(obj1,obj2)
            tf = ~any(ismissing([obj1 obj2])) && ~gt(obj1,obj2);
        end
        function tf = ge(obj1,obj2)
            tf = le(obj2,obj1);
        end

Run the tests with a terse level output detail and review the results.

results = runtests('MissingValueTest','OutputDetail',1);
......
FAIL: MissingValueTest/isequalRules in Missing.isequalRules at 145 :: verifyFalse failed.

FAIL: MissingValueTest/isequalRules in Missing.isequalRules at 147 :: verifyTrue failed.
.
FAIL: MissingValueTest/IsMissing2ndInput in Missing.IsMissing2ndInput at 154 :: verifyTrue failed.
...

Iteratively update MyDataClass to satisfy the equality rules. Define isqual and isequaln in the methods block of MyDataClass.

        % Class supports isequal/isequaln rules
        function tf = isequal(obj1,obj2)
            tf = eq(obj1,obj2);
        end
        function tf = isequaln(obj1,obj2)
            tf = all(ismissing([obj1 obj2])) || eq(obj1,obj2);
        end

Run the tests and review the results. The tests pass and MyDataClass satisfies the missing value contract.

results = runtests('MissingValueTest');
Running MissingValueTest
..........
Done MissingValueTest
__________

More About

expand all

Introduced in R2018b