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)
-
Выполняет встроенные тесты из первого файла в loadpath, соответствующего name.
testможет быть вызван в командной или функциональной форме. Точное поведение test определяется сочетанием режима (интерактивный или пакетный), уровня отчётности ("quiet","normal","verbose") и использования файла журнала или переменной сводного отчёта.По умолчанию, когда
testвызывается из командной строки, режим интерактивный. В этом режиме тесты выполняются до первой ошибки или успешного завершения всех тестов. В пакетном режиме все тесты выполняются независимо от ошибок, и результаты собираются для отчёта. Тесты, требующие взаимодействия с пользователем, т. е. демонстрационные блоки, никогда не выполняются в пакетном режиме.Пакетный режим включается либо 1) указанием файла журнала с помощью третьего аргумента fname или fid, либо 2) запросом выходного аргумента, такого как success, n и т. д.
Необязательный второй аргумент определяет объём генерируемого вывода и типы выполняемых тестов. Значение по умолчанию —
"normal". Запрос выходного аргумента подавляет вывод заключительного сводного сообщения и промежуточных предупреждений, если не включена подробная отчётность."quiet"-
Выводит сводное сообщение, если все тесты пройдены, или сообщение об ошибке с результатами первого не пройденного теста при наличии сбоев. Не запускает тесты, требующие взаимодействия с пользователем.
"normal"-
Отображает предупреждающие сообщения о пропущенных тестах или провалившихся xtests во время выполнения тестов. Выводит сводное сообщение, если все тесты пройдены, или сообщение об ошибке с результатами первого не пройденного теста при наличии сбоев. Не запускает тесты, требующие взаимодействия с пользователем.
"verbose"Отображает тесты перед выполнением. Выводит все предупреждающие сообщения. В интерактивном режиме запускает все тесты, включая те, которые требуют взаимодействия с пользователем.
Необязательный третий входной аргумент указывает файл журнала, в котором должны записываться результаты тестов. Файл журнала может быть строкой (fname) или идентификатором открытого дескриптора файла (fid). Для включения пакетной обработки, но при этом отображения результатов на экране, используйте
stdoutдля fid.При вызове с единственным выходным аргументом success,
testвозвращает true, если все тесты были успешно пройдены. При вызове с более чем одним выходным аргументом возвращаются количество успешных тестов (n), общее количество тестов в файле (nmax), количество сбоев xtest (nxfail), количество тестов, проваленных из-за известных ошибок (nbug), количество пропущенных тестов из-за отсутствующих функций (nskip), количество пропущенных тестов из-за условий во время выполнения (nrtskip) и количество регрессий (nregression).Пример
test sind ⇒ PASSES 5 out of 5 tests [n, nmax] = test ("sind") ⇒ n = 5 nmax = 5Дополнительные синтаксические варианты вызова
Если второй аргумент является строкой
"grabdemo", содержимое любого встроенного демонстрационного блока извлекается, но не выполняется. Текст всех блоков кода конкатенируется и возвращается как code, а idx — вектор позиций концов каждого демонстрационного блока. Для более простого извлечения демонстрационных блоков из файлов, см. пример.Если второй аргумент равен
"explain", то name игнорируется, а объяснение маркеров строк, используемых вtestотчётах, записывается в файл, указанный в fname или fid.
test сканирует указанный скриптовый файл в поисках строк, начинающихся с идентификатора ‘%!’. Префикс удаляется, а остальная часть строки обрабатывается интерпретатором Octave. Если код генерирует ошибку, то тест считается проваленным.
Поскольку eval() останавливается на первой встреченной ошибке, необходимо разбивать тесты на блоки, причём код каждого блока оценивается независимо. Блоки вводятся с помощью допустимых ключевых слов, таких как test, function или assert, непосредственно следующих за ‘%!’. Блок определяется отступами, как в 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’. Например, разложение одиночного значения разреженной матрицы, svds(), зависит от наличия библиотеки ARPACK. Все тесты для svds начинаются со
%!testif HAVE_ARPACK
Просмотрите config.h или __octave_config_info__ ("build_features"), чтобы увидеть некоторые из возможных значений для проверки.
Иногда во время разработки есть тест, который должен работать, но известно, что он проваливается. Вы всё равно хотите оставить тест, потому что когда окончательный код готов, тест должен пройти, но вы можете не сразу исправить его. Чтобы избежать ненужных отчётов об ошибках для этих известных сбоев, пометьте блок xtest вместо test:
%!xtest assert (1==0)
%!xtest fail ("success=1", "error") В этом случае тест будет запущен, и любой сбой будет сообщён. Однако тестирование не прерывается, и последующие блоки тестов будут обработаны нормально. Другое использование xtest — для статистических тестов, которые должны проходить большую часть времени, но иногда терпят неудачу.
Каждый блок оценивается в собственной среде функций, что означает, что переменные, определённые в одном блоке, не автоматически передаются другим блокам. Если вам нужно обмениваться переменными, то необходимо объявить их как shared, прежде чем использовать их. Например, следующее объявляет переменную a, присваивает ей начальное значение (по умолчанию пустое) и затем использует её в нескольких последующих тестах.
%!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
Следующий фрагмент тривиального кода предоставляет примеры использования fail, assert, error и xtest:
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)
%!xtest 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)
***** xtest 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>присутствует, блок теста интерпретируется как дляxtest. %!testif HAVE_XXX%!testif HAVE_XXX, HAVE_YYY, …%!testif HAVE_XXX, HAVE_YYY …; RUNTIME_COND%!testif … <MESSAGE>-
Проверьте блок только если Octave был скомпилирован с функцией
HAVE_XXX.RUNTIME_COND— это необязательное выражение, которое вычисляется для проверки выполнения какого-либо условия во время выполнения теста. ЕслиRUNTIME_CONDложно, тест пропускается. Если<MESSAGE>присутствует, блок теста интерпретируется как дляxtest. %!xtest%!xtest <MESSAGE>-
Проверьте блок, сообщите об ошибке теста, но не прерывайте тестирование. Если
<MESSAGE>присутствует, тогда текст сообщения отображается при ошибке теста, как показано ниже:!!!!! Known bug: MESSAGE
Если сообщение является целым числом, оно интерпретируется как идентификатор ошибки для отслеживания ошибок Octave и сообщается как
!!!!! Known bug: https://octave.org/testfailure/?BUG-ID
где 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>присутствует, блок теста интерпретируется как дляxtest.
При написании тестов конвенция Octave заключается в том, что строки, начинающиеся с типа блока, не имеют точки с запятой в конце. Однако любой код внутри блока является обычным кодом Octave и обычно имеет завершающую точку с запятой. Например,
## bare block instantiation %!assert (sin (0), 0)
но
## test block with normal Octave code %!test %! assert (sin (0), 0);
Вы также можете создавать скрипты тестов для встроенных функций и собственных функций C++. Для этого поместите файл с именем функции (без расширения .m) в директорию в пути загрузки, и он будет обнаружен функцией 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 ложно (числовой ноль).Любые дополнительные аргументы передаются функции
errorдля обработки. assert (observed, expected)-
Возвращает ошибку, если наблюдаемое значение не совпадает с ожидаемым.
Обратите внимание, что observed и expected могут быть скалярами, векторами, матрицами, строками, массивами ячеек или структурами.
assert (observed, expected, tol)-
Возвращает ошибку, если наблюдаемое значение не совпадает с ожидаемым, но сравнение для числовых данных использует допуск tol.
Если tol положительный, то это абсолютный допуск, который вернёт ошибку, если
abs (observed - expected) > abs (tol).Если tol отрицательный, то это относительный допуск, который вернёт ошибку, если
abs (observed - expected) > abs (tol * expected).Если expected равно нулю, tol всегда будет интерпретироваться как абсолютный допуск.
Если tol не скаляр, его размеры должны совпадать с размерами observed и expected, и тесты выполняются поэлементно.
- : fail (code)
- : fail (code, pattern)
- : fail (code, "warning")
- : fail (code, "warning", pattern)
-
Возвращает true, если code завершается с сообщением об ошибке, соответствующим pattern, иначе возвращает ошибку.
code должно быть в форме строки, которая передаётся интерпретатору Octave через функцию
evalin, т.е., (цитируемой) строковой константой или строковой переменной.Обратите внимание, что если code выполняется успешно, а не завершается ошибкой, выводится ошибка:
expected error <.> but got none
Если вызывается с двумя аргументами, возвращаемое значение будет true только если code завершается с сообщением об ошибке, содержащим pattern (регистрозависимое). Если код завершается ошибкой отличной от указанной в pattern, то выводится сообщение:
expected <pattern> but got <text of actual error>Фигурные скобки не являются частью вывода.
При вызове с опцией
"warning",failвернёт ошибку, если выполнение кода не привело к предупреждению.
© 1996–2022 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v6.4.0/Test-Functions.html