MATLAB Examples

Write Script-Based Unit Tests

This example shows how to write a script that tests a function that you create. The example function computes the angles of a right triangle, and you create a script-based unit test to test the function.

Create rightTri Function to Test

Create this function in a file, rightTri.m, in your current MATLAB® folder. This function takes lengths of two sides of a triangle as input and returns the three angles of the corresponding right triangle. The input sides are the two shorter edges of the triangle, not the hypotenuse.

```function angles = rightTri(sides)

A = atand(sides(1)/sides(2));
B = atand(sides(2)/sides(1));
hypotenuse = sides(1)/sind(A);
C = asind(hypotenuse*sind(A)/sides(1));

angles = [A B C];

end

```

Create Test Script

In your working folder, create a new script, rightTriTest.m. Each unit test checks a different output of the rightTri function. A test script must adhere to the following conventions:

• The name of the script file must start or end with the word 'test', which is case-insensitive.
• Place each unit test into a separate section of the script file. Each section begins with two percent signs (%%), and the text that follows on the same line becomes the name of the test element. If no text follows the %%, MATLAB assigns a name to the test. If MATLAB encounters a test failure, it still runs remaining tests.
• In a test script, the shared variable section consists of any code that appears before the first explicit code section (the first line beginning with %%). Tests share the variables that you define in this section. Within a test, you can modify the values of these variables. However, in subsequent tests, the value is reset to the value defined in the shared variables section.
• In the shared variables section (first code section), define any preconditions necessary for your tests. If the inputs or outputs do not meet this precondition, MATLAB does not run any of the tests. MATLAB marks the tests as failed and incomplete.
• When a script is run as a test, variables defined in one test are not accessible within other tests unless they are defined in the shared variables section (first code section). Similarly, variables defined in other workspaces are not accessible to the tests.
• If the script file does not include any code sections, MATLAB generates a single test element from the full contents of the script file. The name of the test element is the same as the script file name. In this case, if MATLAB encounters a failed test, it halts execution of the entire script.

In rightTriTest.m, write four tests to test the output of rightTri. Use the assert function to test the different conditions. In the shared variables section, define four triangle geometries and define a precondition that the rightTri function returns a right triangle.

```% test triangles
tri = [7 9];
triIso = [4 4];
tri306090 = [2 2*sqrt(3)];
triSkewed = [1 1500];

% preconditions
angles = rightTri(tri);
assert(angles(3) == 90,'Fundamental problem: rightTri not producing right triangle')

%% Test 1: sum of angles
angles = rightTri(tri);
assert(sum(angles) == 180)

angles = rightTri(triIso);
assert(sum(angles) == 180)

angles = rightTri(tri306090);
assert(sum(angles) == 180)

angles = rightTri(triSkewed);
assert(sum(angles) == 180)

%% Test 2: isosceles triangles
angles = rightTri(triIso);
assert(angles(1) == 45)
assert(angles(1) == angles(2))

%% Test 3: 30-60-90 triangle
angles = rightTri(tri306090);
assert(angles(1) == 30)
assert(angles(2) == 60)
assert(angles(3) == 90)

%% Test 4: Small angle approximation
angles = rightTri(triSkewed);
approx = sin(smallAngle);
assert(approx == smallAngle, 'Problem with small angle approximation')

```

Test 1 tests the summation of the triangle angles. If the summation is not equal to 180 degrees, assert throws an error.

Test 2 tests that if two sides are equal, the corresponding angles are equal. If the non-right angles are not both equal to 45 degrees, the assert function throws an error.

Test 3 tests that if the triangle sides are 1 and sqrt(3), the angles are 30, 60, and 90 degrees. If this condition is not true, assert throws an error.

Test 4 tests the small-angle approximation. The small-angle approximation states that for small angles the sine of the angle in radians is approximately equal to the angle. If it is not true, assert throws an error.

Run Tests

Execute the runtests function to run the four tests in rightTriTest.m. The runtests function executes each test in each code section individually. If Test 1 fails, MATLAB still runs the remaining tests. If you execute rightTriTest as a script instead of by using runtests, MATLAB halts execution of the entire script if it encounters a failed assertion. Additionally, when you run tests using the runtests function, MATLAB provides informative test diagnostics.

```result = runtests('rightTriTest'); ```
```Running rightTriTest .. ================================================================================ Error occurred in rightTriTest/Test3_30_60_90Triangle and it did not run to completion. --------- Error ID: --------- 'MATLAB:assertion:failed' -------------- Error Details: -------------- Error using rightTriTest (line 31) Assertion failed. ================================================================================ . ================================================================================ Error occurred in rightTriTest/Test4_SmallAngleApproximation and it did not run to completion. --------- Error ID: --------- '' -------------- Error Details: -------------- Error using rightTriTest (line 39) Problem with small angle approximation ================================================================================ . Done rightTriTest __________ Failure Summary: Name Failed Incomplete Reason(s) =========================================================================== rightTriTest/Test3_30_60_90Triangle X X Errored. --------------------------------------------------------------------------- rightTriTest/Test4_SmallAngleApproximation X X Errored. ```

The test for the 30-60-90 triangle and the test for the small-angle approximation fail in the comparison of floating-point numbers. Typically, when you compare floating-point values, you specify a tolerance for the comparison. In Test 3 and Test 4, MATLAB throws an error at the failed assertion and does not complete the test. Therefore, the test is marked as both Failed and Incomplete.

To provide diagnostic information (Error Details) that is more informative than 'Assertion failed' (Test 3), consider passing a message to the assert function (as in Test 4). Or you can also consider using function-based unit tests.

Revise Test to Use Tolerance

Save rightTriTest.m as rightTriTolTest.m, and revise Test 3 and Test 4 to use a tolerance. In Test 3 and Test 4, instead of asserting that the angles are equal to an expected value, assert that the difference between the actual and expected values is less than or equal to a specified tolerance. Define the tolerance in the shared variables section of the test script so it is accessible to both tests.

For script-based unit tests, manually verify that the difference between two values is less than a specified tolerance. If instead you write a function-based unit test, you can access built-in constraints to specify a tolerance when comparing floating-point values.

```% test triangles
tri = [7 9];
triIso = [4 4];
tri306090 = [2 2*sqrt(3)];
triSkewed = [1 1500];

% Define an absolute tolerance
tol = 1e-10;

% preconditions
angles = rightTri(tri);
assert(angles(3) == 90,'Fundamental problem: rightTri not producing right triangle')

%% Test 1: sum of angles
angles = rightTri(tri);
assert(sum(angles) == 180)

angles = rightTri(triIso);
assert(sum(angles) == 180)

angles = rightTri(tri306090);
assert(sum(angles) == 180)

angles = rightTri(triSkewed);
assert(sum(angles) == 180)

%% Test 2: isosceles triangles
angles = rightTri(triIso);
assert(angles(1) == 45)
assert(angles(1) == angles(2))

%% Test 3: 30-60-90 triangle
angles = rightTri(tri306090);
assert(abs(angles(1)-30) <= tol)
assert(abs(angles(2)-60) <= tol)
assert(abs(angles(3)-90) <= tol)

%% Test 4: Small angle approximation
angles = rightTri(triSkewed);
approx = sin(smallAngle);
assert(abs(approx-smallAngle) <= tol, 'Problem with small angle approximation')

```

Rerun the tests.

```result = runtests('rightTriTolTest'); ```
```Running rightTriTolTest .... Done rightTriTolTest __________ ```

All the tests pass.

Create a table of test results.

```rt = table(result) ```
```rt = 4x6 table Name Passed Failed Incomplete Duration Details _______________________________________________ ______ ______ __________ ________ ____________ 'rightTriTolTest/Test1_SumOfAngles' true false false 0.052362 [1x1 struct] 'rightTriTolTest/Test2_IsoscelesTriangles' true false false 0.010095 [1x1 struct] 'rightTriTolTest/Test3_30_60_90Triangle' true false false 0.01376 [1x1 struct] 'rightTriTolTest/Test4_SmallAngleApproximation' true false false 0.014659 [1x1 struct] ```