Write Setup and Teardown Code Using Classes

Test Fixtures

Test fixtures are setup and teardown code that sets up the pretest state of the system and returns it to the original state after running the test. Setup and teardown methods are defined in the TestCase class by the following method attributes:

  • TestMethodSetup and TestMethodTeardown methods run before and after each test method.

  • TestClassSetup and TestClassTeardown methods run before and after all test methods in the test case.

The testing framework guarantees that TestMethodSetup and TestClassSetup methods of superclasses are executed before those in subclasses.

It is good practice for test authors to perform all teardown activities from within the TestMethodSetup and TestClassSetup blocks using the addTeardown method instead of implementing corresponding teardown methods in the TestMethodTeardown and TestClassTeardown blocks. This guarantees the teardown is executed in the reverse order of the setup and also ensures that the test content is exception safe.

Test Case with Method-Level Setup Code

The following test case, FigurePropertiesTest, contains setup code at the method level. The TestMethodSetup method creates a figure before running each test, and TestMethodTeardown closes the figure afterwards. As discussed previously, you should try to define teardown activities with the addTeardown method. However, for illustrative purposes, this example shows the implementation of a TestMethodTeardown block.

classdef FigurePropertiesTest < matlab.unittest.TestCase
    
    properties
        TestFigure
    end
    
    methods(TestMethodSetup)
        function createFigure(testCase)
            testCase.TestFigure = figure;
        end
    end
    
    methods(TestMethodTeardown)
        function closeFigure(testCase)
            close(testCase.TestFigure)
        end
    end
    
    methods(Test)
        function defaultCurrentPoint(testCase)
            cp = testCase.TestFigure.CurrentPoint;
            testCase.verifyEqual(cp,[0 0], ...
                'Default current point is incorrect')
        end
        
        function defaultCurrentObject(testCase)
            import matlab.unittest.constraints.IsEmpty
            co = testCase.TestFigure.CurrentObject;
            testCase.verifyThat(co,IsEmpty, ...
                'Default current object should be empty')
        end
    end
    
end

Test Case with Class-Level Setup Code

The following test case, BankAccountTest, contains setup code at the class level.

To setup the BankAccountTest, which tests the BankAccount class example described in Developing Classes — Typical Workflow, add a TestClassSetup method, addBankAccountClassToPath. This method adds the path to the BankAccount example file. Typically, you set up the path using a PathFixture. This example performs the setup and teardown activities manually for illustrative purposes.

classdef BankAccountTest < matlab.unittest.TestCase
    % Tests the BankAccount class
    
    methods(TestClassSetup)
        function addBankAccountClassToPath(testCase)
            p = path;
            testCase.addTeardown(@path,p)
            addpath(fullfile(matlabroot,'help','techdoc','matlab_oop', ...
                'examples'))
        end
    end
    
    methods(Test)
        function testConstructor(testCase)
            b = BankAccount(1234,100);
            testCase.verifyEqual(b.AccountNumber,1234, ...
                'Constructor failed to correctly set account number')
            testCase.verifyEqual(b.AccountBalance,100, ...
                'Constructor failed to correctly set account balance')
        end
        
        function testConstructorNotEnoughInputs(testCase)
            import matlab.unittest.constraints.Throws
            testCase.verifyThat(@()BankAccount, ...
                Throws('MATLAB:minrhs'))
        end
        
        function testDesposit(testCase)
            b = BankAccount(1234,100);
            b.deposit(25)
            testCase.verifyEqual(b.AccountBalance,125)
        end
        
        function testWithdraw(testCase)
            b = BankAccount(1234,100);
            b.withdraw(25)
            testCase.verifyEqual(b.AccountBalance,75)
        end
        
        function testNotifyInsufficientFunds(testCase)
            callbackExecuted = false;
            function testCallback(~,~)
                callbackExecuted = true;
            end
            b = BankAccount(1234,100);
            b.addlistener('InsufficientFunds',@testCallback);
            b.withdraw(50)
            testCase.assertFalse(callbackExecuted, ...
                'The callback should not have executed yet')
            b.withdraw(60)
            testCase.verifyTrue(callbackExecuted, ...
                'The listener callback should have fired')
        end
    end
    
end

See Also

|

Related Topics