Main Content

Class-Based Unit Tests

You can test your MATLAB® source code by creating unit tests within a test class that inherits from the matlab.unittest.TestCase class. The TestCase class is the superclass of all test classes in MATLAB and provides an interface to write and identify test content, including test fixture setup and teardown routines.

Write your class-based unit tests as Test methods within your test class definition file. A Test method is a method defined in a methods block with the Test attribute. Test methods can use qualifications for testing values and responding to failures. In addition to the Test attribute, TestCase subclasses can leverage a variety of framework-specific attributes to specify tests and test fixtures. For example, you can use the TestMethodSetup and TestMethodTeardown method attributes to specify setup and teardown code for each test in your test class.

Test Class Definition

To write class-based tests, first create a class that derives from the matlab.unittest.TestCase class. Then, specify your unit tests by adding methods to a methods block with the Test attribute within your test class. For example, the MyTestClass class includes two tests (test1 and test2). The first input to a Test method must be a TestCase object, which the test can ignore if its logic does not require it. The TestCase object passed to a Test method provides test-environment-specific information to the corresponding test.

In addition, the MyTestClass class uses framework-specific method attributes to define the setup and teardown methods. The testing framework runs these methods before and after each test, respectively. For more information about setup and teardown code in test classes, see Write Setup and Teardown Code Using Classes.

classdef MyTestClass < matlab.unittest.TestCase
    methods (TestMethodSetup)
        function setup(testCase)
            % Setup code
        end
    end

    methods (TestMethodTeardown)
        function teardown(testCase)
            % Teardown code
        end
    end

    methods (Test)
        function test1(testCase)
            % Test code
        end

        function test2(testCase)
            % Test code
        end
    end
end

Unit tests typically include qualifications for testing values and responding to failures. For example, to test a function, a Test method can specify the actual and expected returned values of the function and then use a qualification method to test for their equality. For illustrative purposes, the PlusTest test class has a Test method for testing the plus function. (In practice, a test class tests user-defined code.) The myTest method calls the verifyEqual qualification method to verify that plus(2,3) produces the expected value 5. When creating your own test class, you have access to the full library of qualifications in the matlab.unittest.qualifications namespace. To determine which qualification to use, see Table of Verifications, Assertions, and Other Qualifications.

classdef PlusTest < matlab.unittest.TestCase
    methods (Test)
        function myTest(testCase)
            actual = plus(2,3);
            expected = 5;
            testCase.verifyEqual(actual,expected)
        end
    end
end

For a simple example of how to write and run class-based unit tests, see Write Simple Test Case Using Classes.

How Test Classes Run

When you run class-based tests (for instance, results = runtests(["TestClassA" "TestClassB" "TestClassC"])), the testing framework first divides the test classes into groups based on their shared test fixtures. (Shared test fixtures are fixtures specified using the SharedTestFixtures attribute of TestCase subclasses.) Each group includes test classes that have exactly the same shared test fixtures. To minimize the required setup and teardown actions, the framework runs the test classes in each group by setting up and tearing down their shared test fixtures a single time. In other words, for each group, the framework:

  1. Sets up the shared test fixtures before running any of the test classes in the group

  2. Runs each test class in the group

  3. Tears down the shared test fixtures after running all the test classes in the group

This diagram shows how the testing framework runs each test class in step 2.

The framework follows these steps when running a test class:

  1. Create class-level TestCase object — The framework creates an object of the test class.

  2. Run class-level setup code — The framework uses the class-level TestCase object to run the class-level setup code specified in the TestClassSetup methods block. The class-level TestCase object reflects the updated environment as a result of the class-level setup code.

  3. Loop over tests:

    1. Create method-level TestCase object — The framework creates a method-level TestCase object by copying the class-level TestCase object that reflects the environment after the execution of the class-level setup code. The framework then passes this object to the TestMethodSetup, Test, and TestMethodTeardown methods of the test class.

      Note

      To prevent a test from affecting the environment of other tests, TestCase instances passed to different Test methods are independent copies. In other words, modifications to the test case in a Test method remain scoped to that method and do not propagate to other Test methods in the test class.

    2. Run method-level setup code — The framework uses the method-level TestCase object to run the method-level setup code specified in the TestMethodSetup methods block. The method-level TestCase object reflects the updated environment as a result of the method-level setup code.

    3. Run test — The framework uses the method-level TestCase object to run the Test method corresponding to the test. If the test is parameterized, the framework uses the parameterization information to run the method.

    4. Run method-level teardown code — The framework uses the method-level TestCase object to run the method-level teardown code specified using a call to the addTeardown method in the TestMethodSetup methods block or in the TestMethodTeardown methods block.

    5. Delete method-level TestCase object — The framework discards the method-level TestCase object used to run the test and its corresponding method-level setup and teardown code.

  4. Run class-level teardown code — The framework uses the class-level TestCase object to run the class-level teardown code specified using a call to the addTeardown method in the TestClassSetup methods block or in the TestClassTeardown methods block.

  5. Delete class-level TestCase object — The framework discards the class-level TestCase object used to run the tests in the test class.

Note

Uncaught errors and qualification failures can affect the test run workflow. For instance, if an assumption failure occurs in the TestClassSetup or TestClassTeardown methods block, the testing framework marks the entire test class as filtered and skips looping over the Test methods.

Test Independence and Repeatability

Unit tests in a matlab.unittest.TestCase subclass must run independently, without unintentionally affecting one another. In addition, they must be repeatable, which means that a running test must not affect subsequent reruns of the same test. For test independence and repeatability, follow these best practices when creating a test class:

  • If you add code to your test class for setting up the test environment, also include code to restore the environment to its original state by performing teardown actions symmetrically in the reverse order of their corresponding setup actions.

  • To access a global state, such as the MATLAB search path or output display format, use a method instead of a default property value.

  • To specify test parameter values, use value objects instead of handle objects.

For more information, see Write Independent and Repeatable Tests.

Features of Class-Based Tests

Class-based tests provide you with several advanced test authoring features and give you access to the full MATLAB unit testing framework functionality. For example, you can use advanced qualification features, including constraints, actual value proxies, tolerances, and test diagnostics, in your class-based tests. In addition, with class-based tests, you can:

  • Share fixtures among test classes. For more information, see Write Tests Using Shared Fixtures.

  • Group tests into categories and then run the tests with specified tags. For more information, see Tag Unit Tests.

  • Write parameterized tests to combine and execute tests on specified lists of parameters. For more information, see Use Parameters in Class-Based Tests.

  • Use subclassing and inheritance to share and reuse test content. For example, you can reuse the parameters and methods defined in a test class by deriving subclasses. For more information, see Hierarchies of Classes — Concepts.

See Also

Classes

Related Topics