Main Content

编写基于脚本的单元测试

此示例演示了如何编写脚本,对您创建的函数进行测试。该示例函数可计算直角三角形的角度,您还创建一个基于脚本的单元测试来测试该函数。

创建待测试的 rightTri 函数

在您的当前 MATLAB® 文件夹下的 rightTri.m 文件中创建以下函数。此函数将三角形的两条边长作为输入,返回所对应直角三角形的三个角的度数。输入的边是三角形两个较短的边,而不是斜边。

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

创建测试脚本

在您的工作文件夹中,创建一个新脚本 rightTriTest.m。每个单元测试对 rightTri 函数的不同输出进行检查。测试脚本必须遵循以下惯例:

  • 测试文件的名称必须以单词“test”开头或结尾,且不区分大小写。如果文件名不以单词“test”开头或结尾,则在某些情况下,文件中的测试可能被忽略。

  • 将每个单元测试放到脚本文件的单独部分。每个部分以两个百分比符号 (%%) 开始,同一行中紧跟百分比符号的文本将成为测试元素的名称。如果 %% 后面没有文本,则 MATLAB 会为测试分配一个名称。如果 MATLAB 遇到一次测试失败,则仍将运行剩余的测试。

  • 在测试脚本中,共享变量部分包含在第一个显式代码节(第一个以 %% 开头的行)之前出现的所有代码。各测试将共享您在这个部分定义的变量。在一个测试内,您可以修改这些变量的值。但在后续测试中,该值会重置为在共享变量部分定义的值。

  • 在共享变量部分(第一个代码节)中,为您的测试定义所有必要的先决条件。如果输入或输出不满足此先决条件,MATLAB 不会运行这些测试中的任何一个。MATLAB 将测试标记为失败和不完整。

  • 在运行脚本进行测试时,一个测试中定义的变量在其他测试中不可访问,除非这些变量是在共享变量部分(第一个代码节)定义的。同样,这些测试也不能访问在其他工作区中定义的变量。

  • 如果脚本文件不包含任何代码节,则 MATLAB 将从脚本文件的全部内容生成为单个测试元素。测试元素的名称与脚本文件名相同。这种情况下,如果 MATLAB 遇到失败的测试,它会停止执行整个脚本。

rightTriTest.m 中,编写四个测试来测试 rightTri 的输出。使用 assert 函数测试不同的条件。在共享变量部分,定义四个三角形,并定义 rightTri 函数返回直角这一先决条件。

% 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);
smallAngle = (pi/180)*angles(1); % radians
approx = sin(smallAngle);
assert(approx == smallAngle, 'Problem with small angle approximation')

测试 1 测试三角形的角度总和。如果总和不等于 180 度,assert 将引发错误。

测试 2 测试如果两条边相等,则对应的角也相等。如果非直角不都等于 45 度,assert 函数将引发错误。

测试 3 测试如果三角形的边为 1sqrt(3),则角度分别为 30、60 和 90 度。如果不满足此条件,assert 将引发错误。

测试 4 测试小角度近似。小角度近似是指对于小角度而言,以弧度表示的角度正弦值约等于该角度。如果不满足此条件,assert 将引发错误。

运行测试

执行 runtests 函数以运行 rightTriTest.m 中的四个测试。runtests 函数单独执行每个代码节中的每个测试。如果测试 1 失败,MATLAB 仍会运行剩余的测试。如果您将 rightTriTest 作为脚本执行,而不是通过使用 runtests 来执行,MATLAB 会在遇到失败断言时停止执行整个脚本。此外,当您使用 runtests 函数运行测试时,MATLAB 可提供包含有用信息的测试诊断。

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.

30-60-90 三角形测试和小角度近似测试在比较浮点数时失败。通常,当您比较浮点值时,需要指定比较的容差。在测试 3 和测试 4 中,MATLAB 在出现失败断言时引发错误,并且不完成测试。因此,测试同时被标记为 FailedIncomplete

要提供比 'Assertion failed'(测试 3)更全面的诊断信息 (Error Details),可考虑向 assert 函数传递消息(如测试 4 中所示)。或者也可以考虑使用基于函数的单元测试。

修改测试以使用容差

rightTriTest.m 另存为 rightTriTolTest.m,并修订测试 3 和测试 4 以使用容差。在测试 3 和测试 4 中,并不断言角度等于某个预期值,而是断言实际值与预期值之间的差值小于或等于指定的容差。在测试脚本的共享变量部分定义该容差,以便两个测试均可访问它。

对于基于脚本的单元测试,请手动校验两个值之间的差小于指定容差。但如果您编写基于函数的单元测试,则可以访问内置约束以指定在比较浮点值时的容差。

% 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);
smallAngle = (pi/180)*angles(1); % radians
approx = sin(smallAngle);
assert(abs(approx-smallAngle) <= tol, 'Problem with small angle approximation')

重新运行测试。

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

成功通过所有测试。

创建测试结果表格。

rt = table(result)
rt =

  4×6 table

                          Name                           Passed    Failed    Incomplete    Duration       Details   
    _________________________________________________    ______    ______    __________    _________    ____________

    {'rightTriTolTest/Test1_SumOfAngles'            }    true      false       false         0.02373    {1×1 struct}
    {'rightTriTolTest/Test2_IsoscelesTriangles'     }    true      false       false       0.0047332    {1×1 struct}
    {'rightTriTolTest/Test3_30_60_90Triangle'       }    true      false       false       0.0051982    {1×1 struct}
    {'rightTriTolTest/Test4_SmallAngleApproximation'}    true      false       false       0.0049869    {1×1 struct}

另请参阅

|

相关主题