B.1测试函数

 
: test name
: test name quiet|normal|verbose
: test ("name", "quiet|normal|verbose", fid)
: test ("name", "quiet|normal|verbose", fname)
: success = test (…)
: [n, nmax, nxfail, nbug, nskip, nrtskip, nregression] = test (…)
: [code, idx] = test ("name", "grabdemo")
: test ([], "explain", fid)
: test ([], "explain", fname)

从加载路径name匹配中的第一个文件执行内置测试.

test可以以命令或函数形式调用。测试的精确操作由模式(交互式或观察)、返回级别的组合决定("quiet","normal","verbose"),以及是否使用日志文件或摘要返回变量决定。

test从命令行调用时,默认模式是交互的。在这种模式下,将运行测试,直到第一个错误被消除,或者所有测试都成功完成。在批处理模式下,所有测试都将运行,而不考虑任何失败,并收集结果以进行返回。需要用户交互的测试,即演示块,永远不会以批处理模式运行。

批处理模式可通过以下方式启用:1)使用第三层指定日志文件fnamefid,或2)指定输出参数,例如success,n

可选的第二个参数确定要生成的输出量以及要运行的测试类型。默认值为"normal"。除非启用了详细返回,否则指定输出参数将禁止打印最终汇总消息和任何中间警告。

"quiet"

当所有测试都通过时,打印一条摘要消息,或者当失败时,打印带有第一个错误测试结果的错误。不要运行需要用户交互的测试。

"normal"

在测试执行期间显示有关跳过的测试或失败的测试的警告消息。当所有测试都通过时,打印一条摘要消息,或者当失败时,打印带有第一个错误测试结果的错误。不要运行需要用户交互的测试。

广告
"verbose"

执行前显示测试。打印所有警告消息。在交互模式下,运行所有测试,包括那些需要用户交互的测试。

广告

可选的第三个输入参数指定了应该写入测试结果的日志文件。日志文件可以是字符串(fname)或打开的文件描述符ID(fid). 要启用批处理,但仍将结果打印到屏幕上,请使用stdout作为fid.

仅使用单个输出参数success调用时,test如果所有测试都成功,则返回true。如果使用多个输出参数调用,则成功测试的数量(n),文件中的测试总数(nmax),测试问题的数量(nxfail),因为已知错误而失败的测试数(nbug),因为缺少函数而跳过的测试数(nskip),因为运行时条件而跳过的测试数(nrtskip),以及回归次数(nregression)返回。

用例

test sind
⇒
PASSES 5 out of 5 tests

[n, nmax] = test (sind")
⇒
n =  5
nmax =  5

附加调用Syntax

如果第二个参数是字符串"grabdemo",任何内置演示块的内容都会被提取,但不会被执行。所有代码块code的文本在每个演示块末端位置连接idx并返回。有关从文件中提取演示块的更简单方法,详见example.

如果第二个参数是"explain",那么name被忽略,并且解释test中使用的|符号,输出写入指定的文件fnamefid中.

详见: assert,fail,demo,example,error.

广告

test扫描命名脚本文件,查找以标识符“%!”开头的行. 前缀被去除,行的剩余部分通过Octave解释器进行处理。如果代码生成错误,则称测试失败。

自由eval()将在遇到第一个错误时停止,您必须将测试划分为多个块,并分别评估单独块中的任何内容。块从通过关键字引入,如test,functionassert跟在%!之后.块是通过Python中的缩进来定义的。以'%!<whitespace>'开头的行是块前面的一部分。

例如

%!test error (this test fails!")
%!test "test doesn't fail.  it doesn't generate an error"

当测试失败时,您将看到以下内容:

  ***** test error (this test fails!")
!!!!! test failed
this test fails!

通常,为了测试某个东西是否通过,您需要断言它返回了正确的值。真正的测试可能看起来像

%!test
%! a = [1, 2, 3; 4, 5, 6]; B = [1; 2];
%! expect = [ a ; 2*a ];
%! get = kron (b, a);
%! if (any (size (expect) != size (get)))
%!   error (wrong size: expected %d,%d but got %d,%d",
%!          size (expect), size (get));
%! elseif (any (any (expect != get)))
%!   error (didn't get what was expected.");
%! endif

为了简化过程,请使用assert,例如之前使用assert的测试被简化为:

%!test
%! a = [1, 2, 3; 4, 5, 6]; b = [1; 2];
%! assert (kron (b, a), [ a; 2*a ]);

assert可以接受一个误差范围,这样你就可以解决或相对地比较结果。例如,以下全部成功:

%!test assert (1+eps, 1, 2*eps)           # absolute error
%!test assert (100+100*eps, 100, -2*eps)  # relative error

您也可以自己进行比较,但仍有assert产生错误:

%!test assert (isempty ([]))
%!test assert ([1, 2; 3, 4] > 0)

因为assert在测试块中经常单独使用,有一种简写形式:

%!assert (...)

其相当于:

%!test assert (...)

有时,一组测试将取决于在Octave中是否具有可选函数。在测试这些块之前,必须检查所需函数的可用性。一个%!testif HAVE_XXX只有在Octave是使用函数编译的情况下,块才会运行HAVE_XXX. 例如稀疏single值分解,svds(),所有以svds…开始的测试取决于是否具有ARPACK依赖库

%!testif HAVE_ARPACK

详见config.h__octave_config_info__ ("build_features")以查看要检查的一些可能值。

有时,在开发过程中,有一个测试本应通过,但却失败了。您仍然希望保留测试,因为当最终代码准备好时,测试应该会通过,但您可能无法立即修复它。为了避免这些已知问题的不必要的错误返回,请在块上标记test而不直接使用test:

%!test assert (1==0)
%!test fail (success=1", "error")

在这种情况下,将运行测试,并返回任何失败。但是,测试不会中止,后续测试块将正常处理。test的另一个用途是给统计学家的,他们大部分时间都应该通过,但偶尔会失败。

每个块都在其自己的函数环境中进行评估,这意味着一个块中定义的变量不会自动与其他块共享。如果确实要共享变量,则在使用之前必须将它们声明为shared。例如,以下内容声明了变量a,给它一个初始值(defaultis empty),然后在随后的几个测试中使用它。

%!shared a
%! a = [1, 2, 3; 4, 5, 6];
%!assert (kron ([1; 2], a), [ a; 2*a ])
%!assert (kron ([1, 2], a), [ a, 2*a ])
%!assert (kron ([1,2; 3,4], a), [ a,2*a; 3*a,4*a ])

您可以同时共享多个变量:

%!shared a, b

对共享变量的修改从一个测试持续到下一个测试当且仅当测试成功。因此,如果一个测试修改了共享变量,那么后面的测试就无法知道共享变量的预期值,因为前面测试的通过/失败状态是未知的。因此,不建议在测试中修改共享变量。

您还可以共享测试函数:

%!function a = fn (b)
%!  a = 2*b;
%!endfunction
%!assert (fn(2), 4)

请注意,当声明共享块时,所有前一个变量和值都将丢失。

记住这一点:%!function开始一个新的区块,并且%!endfunction结束此块。请注意,在启动新块之前,以'%!<space>'开头的行将作为注释丢弃。以下内容与上面的示例几乎相同,但没有任何作用。

%!function a = fn (b)
%!  a = 2*b;
%!endfunction
%!assert (fn(2), 4)

因为%!后面有一个空格,所以这里的assert声明并没有开始一个新的块,这一行被视为注释。

错误和警告块类似于测试块,但只有当代码生成错误时,它们才会成功。您可以使用可选的正则表达式<pattern>来检查错误的文本是否正确,例如

%!error <passes!> error (this test passes!")

如果代码没有生成错误,则测试失败。例如

%!error "this is an error because it succeeds."

生产

  ***** error "this is an error because it succeeds."
!!!!! test failed: no error

尽可能地自动化测试是很重要的,尽管有些测试需要用户交互。这些可以隔离到演示块中,如果您处于批处理模式,则仅在使用demo或者verbose参数调用时运行test。代码在执行之前显示。例如

%!demo
%! t = [0:0.01:2*pi]; x = sin (t);
%! plot (t, x);
%! # you should now see a sine wave in your figure window

生产

funcname example 1:
 t = [0:0.01:2*pi]; x = sin (t);
 plot (t, x);
 # you should now see a sine wave in your figure window

Press <enter> to continue:

请注意,演示块不能使用任何共享变量。这样它们就可以自己执行,而忽略所有其他测试。

如果要临时禁用测试块,请将#代替块类型。这将创建一个注释块,该注释块在日志文件中回显显示但未执行。例如

%!#demo
%! t = [0:0.01:2*pi]; x = sin (t);
%! plot (t, x);
%! # you should now see a sine wave in your figure window

以下琐碎的代码片段提供了使用il、assert、error和测试的示例:

function output = must_be_zero (input)
  if (input != 0)
    error (Nonzero input!")
  endif
  output = input;
endfunction

%!fail (must_be_zero (1)")
%!assert (must_be_zero (0), 0)
%!error <Nonzero> must_be_zero (1)
%!test error (This code generates an error")

将其放入文件时must_be_zero.m,并且运行测试,我们看到

test must_be_zero verbose

⇒
>>>>> /path/to/must_be_zero.m
***** fail (must_be_zero (1)")
***** assert (must_be_zero (0), 0)
***** error <Nonzero> must_be_zero (1)
***** 测试 error (This code generates an error")
!!!!! known failure
This code generates an error
PASSES 3 out of 4 tests (1 expected failure)

块类型摘要:

%!test
%!test <MESSAGE>

检查整个块是否正确。如果<MESSAGE>存在,测试块被解释为test.

广告
%!testif HAVE_XXX
%!testif HAVE_XXX, HAVE_YYY, …
%!testif HAVE_XXX, HAVE_YYY …; RUNTIME_COND
%!testif … <MESSAGE>

仅当Octave是使用函数编译时才检查块HAVE_XXX . RUNTIME_COND 是一个可选表达式,用于在执行测试时评估以检查是否满足某些条件。如果RUNTIME_COND 为false,则跳过测试。如果<MESSAGE>存在时,测试块被解释为test.

广告
%!test
%!test <MESSAGE>

检查块,返回测试失败,但不要中止测试。如果<MESSAGE>如果存在,则在测试失败时显示消息文本,如下所示:

!!!!! known bug:  MESSAGE

如果消息是一个整数,它将被解释为Octave错误跟踪器的错误ID,并返回为

!!!!! known bug: https://octave.org/testfailure/?BUG-ID

其中BUG-ID是整数错误号。其目的是允许对已知问题进行更清晰的记录。

如果MESSAGE是前面有星号的整数(例如*12345),它被解释为已关闭的错误返回的id。这通常意味着在这里的测试中探测到的问题已经解决。如果此类测试失败,则test的返回可用于回归测试

!!!!! regression: https://octave.org/testfailure/?BUG-ID
广告
%!error
%!error <MESSAGE>
%!warning
%!warning <MESSAGE>

检查是否有正确的错误或警告信息。如果<MESSAGE>如果已应用,则将其解释为期望与错误或警告消息匹配的正则表达式。

广告
%!demo

演示仅在交互模式下执行。

广告
%!#

忽略块中的所有内容

广告
%!shared x,y,z

声明在多个测试中使用的变量。

广告
%!function

定义一个用于多个测试的函数。

广告
%!endfunction

结束函数定义。

广告
%!assert (x, y, tol)
%!assert <MESSAGE> (x, y, tol)
%!fail (CODE, PATTERN)
%!fail <MESSAGE> (CODE, PATTERN)

%!test assert (x, y, tol)%!test fail (CODE, PATTERN)的简写形式。如果<MESSAGE>存在,测试块被解释为test.

广告

当编码测试时,Octave约定是以块类型开头的行末尾没有分号。然而,块中的任何代码都是正常的Octave代码,并且通常会有一个尾随的分号。例如

## bare block instantiation
%!assert (sin (0), 0)

但是

## test block with normal Octave code
%!test
%! assert (sin (0), 0);

您还可以为内置函数和您自己的C++函数创建测试脚本。要做到这一点,请将一个具有裸函数名(no.mextension)的文件放在加载路径的目录中,它将被test作用。或者,您可以将测试直接嵌入到C++代码中:

/*
%!test disp (this is a test")
*/

#if 0
%!test disp (this is a test")
#endif

然而,在这种情况下,原始源代码需要位于加载路径中,并且用户必须记住输入test ("funcname.cc").

 
: assert (cond)
: assert (cond, errmsg)
: assert (cond, errmsg, …)
: assert (cond, msg_id, errmsg, …)
: assert (observed, expected)
: assert (observed, expected, tol)

如果不满足指定的条件,则会返回错误。

assert可以用三种不同的方式调用。

assert (cond)
assert (cond, errmsg)
assert (cond, errmsg, …)
assert (cond, msg_id, errmsg, …)

如果使用单个参数cond调用,那么assert cond是否为false(数字零)。

任何其他参数都会传递给error函数进行处理。

广告
assert (observed, expected)

如果观察到的与预期的不一样,则返回错误。

请注意observedexpected可以是标量、向量、矩阵、字符串、元胞数组或结构体。

广告
assert (observed, expected, tol)

如果观察到与预期不相同,但数值数据的相等比较使用误差范围,则返回错误tol.

如果tol是正的,那么它是一个绝对误差范围,即是否abs (observed - expected) > abs (tol).

如果tol为负,则为相对误差范围,即是否abs (observed - expected) > abs (tol * expected).

如果expected为零,那么tol将始终被解释为不接受误差。

如果tol不是标量,其维度必须与observedexpected的维度一致,并且按元素进行测试。

广告

详见: fail,test,error,isequal.

广告
: status = fail (code)
: status = fail (code, pattern)
: status = fail (code, "warning")
: status = fail (code, "warning", pattern)

如果返回true,则代表code失败,错误消息与pattern匹配,否则会返回false。

code必须采用字符串的形式,该字符串通过evalin函数,即(带引号的)字符串常量或字符串变量。

请注意,如果code成功运行,而未失败,那么打印的错误为:

          expected error <.> but got none

如果使用两个参数调用,则返回值只有在code失败,错误消息包含pattern(区分大小写)。如果代码失败,错误与pattern中指定的错误不同,则返回的消息是:

          expected <pattern>
          but got <text of actual error>

尖括号不是输出的一部分。

在使用"warning"参数调用fail时,如果执行代码没有返回警告,那么将返回false。

详见: assert,error.

广告

版权所有 © 2024-2025 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2