Create Custom Boolean Constraint

This example shows how to create a custom Boolean constraint that determines if a given value has the same size as an expected value.

In a file in your current folder, create a class named HasSameSizeAs that derives from the matlab.unittest.constraints.BooleanConstraint class. The class constructor accepts an expected value whose size is compared to the size of an actual value. The expected value is stored in the ValueWithExpectedSize property. The recommended practice is to make BooleanConstraint implementations immutable, so set the property SetAccess attribute to immutable.

classdef HasSameSizeAs < matlab.unittest.constraints.BooleanConstraint
    
    properties(SetAccess = immutable)
        ValueWithExpectedSize
    end
    
    methods
        function constraint = HasSameSizeAs(value)
            constraint.ValueWithExpectedSize = value;
        end
    end
    
end

In a methods block with private access, define a helper method sizeMatchesExpected that determines if the actual and expected values have the same size. This method is invoked by other constraint methods.

methods(Access = private)
    function bool = sizeMatchesExpected(constraint,actual)
        bool = isequal(size(actual),size(constraint.ValueWithExpectedSize));
    end
end

The matlab.unittest.constraints.BooleanConstraint class is a subclass of the matlab.unittest.constraints.Constraint class. Therefore, classes that derive from the BooleanConstraint class must override the methods of the Constraint class. Within a methods block, override the satisfiedBy and getDiagnosticFor methods. The satisfiedBy implementation must contain the comparison logic and return a logical value. The getDiagnosticFor implementation must evaluate the actual value against the constraint and provide a Diagnostic object. In this example, getDiagnosticFor returns a StringDiagnostic object.

methods
    function bool = satisfiedBy(constraint,actual)
        bool = constraint.sizeMatchesExpected(actual);
    end
        
    function diag = getDiagnosticFor(constraint,actual)
        import matlab.unittest.diagnostics.StringDiagnostic
        if constraint.sizeMatchesExpected(actual)
            diag = StringDiagnostic('HasSameSizeAs passed.');
        else
            diag = StringDiagnostic(sprintf(...
                'HasSameSizeAs failed.\nActual Size: [%s]\nExpectedSize: [%s]',...
                int2str(size(actual)),...
                int2str(size(constraint.ValueWithExpectedSize))));
        end
    end
end

Classes that derive from BooleanConstraint must implement the getNegativeDiagnosticFor method. This method must provide a Diagnostic object when the constraint is negated.

Override getNegativeDiagnosticFor in a methods block with protected access.

methods(Access = protected)
    function diag = getNegativeDiagnosticFor(constraint,actual)
        import matlab.unittest.diagnostics.StringDiagnostic
        if constraint.sizeMatchesExpected(actual)
            diag = StringDiagnostic(sprintf(...
                ['Negated HasSameSizeAs failed.\nSize [%s] of '...
                'Actual Value and Expected Value were the same '...
                'but should not have been.'],int2str(size(actual))));
        else
            diag = StringDiagnostic('Negated HasSameSizeAs passed.');
        end
    end
end

In exchange for implementing the required methods, the constraint inherits the appropriate and, or, and not overloads, so it can be combined with other BooleanConstraint objects or negated.

HasSameSizeAs Class Definition

This is the complete code for the HasSameSizeAs class.

classdef HasSameSizeAs < matlab.unittest.constraints.BooleanConstraint
    
    properties(SetAccess = immutable)
        ValueWithExpectedSize
    end
    
    methods
        function constraint = HasSameSizeAs(value)
            constraint.ValueWithExpectedSize = value;
        end
        
        function bool = satisfiedBy(constraint,actual)
            bool = constraint.sizeMatchesExpected(actual);
        end
        
        function diag = getDiagnosticFor(constraint,actual)
            import matlab.unittest.diagnostics.StringDiagnostic
            
            if constraint.sizeMatchesExpected(actual)
                diag = StringDiagnostic('HasSameSizeAs passed.');
            else
                diag = StringDiagnostic(sprintf(...
                    'HasSameSizeAs failed.\nActual Size: [%s]\nExpectedSize: [%s]',...
                    int2str(size(actual)),...
                    int2str(size(constraint.ValueWithExpectedSize))));
            end
        end
    end
    
    methods(Access = protected)
        function diag = getNegativeDiagnosticFor(constraint,actual)
            import matlab.unittest.diagnostics.StringDiagnostic
            if constraint.sizeMatchesExpected(actual)
                diag = StringDiagnostic(sprintf(...
                    ['Negated HasSameSizeAs failed.\nSize [%s] of '...
                    'Actual Value and Expected Value were the same '...
                    'but should not have been.'],int2str(size(actual))));
            else
                diag = StringDiagnostic('Negated HasSameSizeAs passed.');
            end
        end
    end

    methods(Access = private)
        function bool = sizeMatchesExpected(constraint,actual)
            bool = isequal(size(actual),size(constraint.ValueWithExpectedSize));
        end
    end

end

Test for Expected Size

At the command prompt, create a test case for interactive testing.

import matlab.unittest.TestCase
import matlab.unittest.constraints.HasLength
testCase = TestCase.forInteractiveUse;

Test a passing case. The test passes because one of the or conditions, HasLength(5), is true.

testCase.verifyThat(zeros(5),HasLength(5) | ~HasSameSizeAs(repmat(1,5)))
Verification passed.

Test a failing case. The test fails because one of the and conditions, ~HasSameSizeAs(repmat(1,5)), is false.

testCase.verifyThat(zeros(5),HasLength(5) & ~HasSameSizeAs(repmat(1,5)))
Verification failed.
    ---------------------
    Framework Diagnostic:
    ---------------------
    AndConstraint failed.
    --> + [First Condition]:
         |   HasLength passed.
         |   
         |   Actual Value:
         |        0     0     0     0     0
         |        0     0     0     0     0
         |        0     0     0     0     0
         |        0     0     0     0     0
         |        0     0     0     0     0
         |   Expected Length:
         |        5
    --> AND
        + [Second Condition]:
         |   Negated HasSameSizeAs failed.
         |   Size [5  5] of Actual Value and Expected Value were the same but should not have been.
        -+---------------------

See Also

| | | | | |

Related Topics