Class-Based Unit Tests - MATLAB & Simulink (original) (raw)
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 theTest
attribute. Test
methods can use qualifications for testing values and responding to failures. In addition to theTest
attribute, TestCase
subclasses can leverage a variety of framework-specific attributes to specify tests and test fixtures. For example, you can use the TestMethodSetup
andTestMethodTeardown
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 thematlab.unittest.TestCase
class. Then, specify your unit tests by adding methods to a methods
block with theTest
attribute within your test class. For example, theMyTestClass
class includes two tests (test1
andtest2
). 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 aTest
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, thePlusTest
test class has a Test
method for testing the plus
function. (In practice, a test class tests user-defined code.) The myTest
method calls theverifyEqual
qualification method to verify thatplus(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 theSharedTestFixtures
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:
- Sets up the shared test fixtures before running any of the test classes in the group
- Runs each test class in the group
- 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:
- Create class-level
TestCase
object — The framework creates an object of the test class. - Run class-level setup code — The framework uses the class-level
TestCase
object to run the class-level setup code specified in theTestClassSetup
methods
block. The class-levelTestCase
object reflects the updated environment as a result of the class-level setup code. - Loop over tests:
- Create method-level
TestCase
object — The framework creates a method-levelTestCase
object by copying the class-levelTestCase
object that reflects the environment after the execution of the class-level setup code. The framework then passes this object to theTestMethodSetup
,Test
, andTestMethodTeardown
methods of the test class.
Note
To prevent a test from affecting the environment of other tests,TestCase
instances passed to differentTest
methods are independent copies. In other words, modifications to the test case in aTest
method remain scoped to that method and do not propagate to otherTest
methods in the test class. - Run method-level setup code — The framework uses the method-level
TestCase
object to run the method-level setup code specified in theTestMethodSetup
methods
block. The method-levelTestCase
object reflects the updated environment as a result of the method-level setup code. - Run test — The framework uses the method-level
TestCase
object to run theTest
method corresponding to the test. If the test is parameterized, the framework uses the parameterization information to run the method. - 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 theaddTeardown
method in theTestMethodSetup
methods
block or in theTestMethodTeardown
methods
block. - Delete method-level
TestCase
object — The framework discards the method-levelTestCase
object used to run the test and its corresponding method-level setup and teardown code.
- Create method-level
- 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 theaddTeardown
method in theTestClassSetup
methods
block or in theTestClassTeardown
methods
block. - Delete class-level
TestCase
object — The framework discards the class-levelTestCase
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 theTestClassSetup
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.