Main Content

Create Custom Boolean Constraint

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

In a file in your current folder, create a class named IsSameSizeAs 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 IsSameSizeAs < matlab.unittest.constraints.BooleanConstraint
    properties (SetAccess=immutable)
        ValueWithExpectedSize
    end
    
    methods
        function constraint = IsSameSizeAs(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 are the same size. This method is invoked by other constraint methods.

    methods (Access=private)
        function tf = sizeMatchesExpected(constraint,actual)
            tf = 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 implement the methods of the Constraint class. Within a methods block, implement 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 tf = satisfiedBy(constraint,actual)
            tf = constraint.sizeMatchesExpected(actual);
        end

        function diagnostic = getDiagnosticFor(constraint,actual)
            import matlab.automation.diagnostics.StringDiagnostic
            if constraint.sizeMatchesExpected(actual)
                diagnostic = StringDiagnostic("IsSameSizeAs passed.");
            else
                diagnostic = StringDiagnostic( ...
                    "IsSameSizeAs failed." + newline + "Actual Size: [" ...
                    + int2str(size(actual)) + "]" + newline ...
                    + "Expected Size: [" ...
                    + 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. Implement getNegativeDiagnosticFor in a methods block with protected access.

    methods (Access=protected)
        function diagnostic = getNegativeDiagnosticFor(constraint,actual)
            import matlab.automation.diagnostics.StringDiagnostic
            if constraint.sizeMatchesExpected(actual)
                diagnostic = StringDiagnostic( ...
                    "Negated IsSameSizeAs failed." + newline + ...
                    "Actual and expected sizes were the same ([" ...
                    + int2str(size(actual)) + ...
                    "]) but should not have been.");
            else
                diagnostic = StringDiagnostic( ...
                    "Negated IsSameSizeAs 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.

IsSameSizeAs Class Definition

This is the complete code for the IsSameSizeAs class.

classdef IsSameSizeAs < matlab.unittest.constraints.BooleanConstraint
    properties (SetAccess=immutable)
        ValueWithExpectedSize
    end

    methods
        function constraint = IsSameSizeAs(value)
            constraint.ValueWithExpectedSize = value;
        end

        function tf = satisfiedBy(constraint,actual)
            tf = constraint.sizeMatchesExpected(actual);
        end

        function diagnostic = getDiagnosticFor(constraint,actual)
            import matlab.automation.diagnostics.StringDiagnostic
            if constraint.sizeMatchesExpected(actual)
                diagnostic = StringDiagnostic("IsSameSizeAs passed.");
            else
                diagnostic = StringDiagnostic( ...
                    "IsSameSizeAs failed." + newline + "Actual Size: [" ...
                    + int2str(size(actual)) + "]" + newline ...
                    + "Expected Size: [" ...
                    + int2str(size(constraint.ValueWithExpectedSize)) ...
                    + "]");
            end
        end
    end

    methods (Access=protected)
        function diagnostic = getNegativeDiagnosticFor(constraint,actual)
            import matlab.automation.diagnostics.StringDiagnostic
            if constraint.sizeMatchesExpected(actual)
                diagnostic = StringDiagnostic( ...
                    "Negated IsSameSizeAs failed." + newline + ...
                    "Actual and expected sizes were the same ([" ...
                    + int2str(size(actual)) + ...
                    "]) but should not have been.");
            else
                diagnostic = StringDiagnostic( ...
                    "Negated IsSameSizeAs passed.");
            end
        end
    end

    methods (Access=private)
        function tf = sizeMatchesExpected(constraint,actual)
            tf = 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) | ~IsSameSizeAs(repmat(1,5)))
Verification passed.

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

testCase.verifyThat(zeros(5),HasLength(5) & ~IsSameSizeAs(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 ISameSizeAs failed.
         |   Actual and expected sizes were the same ([5  5]) but should not have been.
        -+---------------------

See Also

Classes

Related Topics