我正在编写 Python 的 doctest
版本测试员,for MATLAB (它部分有效......)。为此,我需要在人们的 m 文件帮助中运行示例中的代码。我希望变量从一行转移到下一行,例如
% >> I = 5 + 33; % expect no output
% >> I
%
% I =
%
% 38
%
为了运行测试,我对搜索测试的 REGEX 进行了匹配循环。对于每场比赛,我 evalc
示例并确保结果匹配:
for I = 1:length(examples)
try
got = evalc(examples(I).source);
catch exc
got = ['??? ' exc.message];
end
% process the result...
end
问题是示例中 I
的定义现在已经破坏了我循环中的循环变量,因为赋值是从 eval
继承过来的进入外部范围。我四处寻找能够创建新范围/工作区的东西,但是 evalin
只能重新使用调用者的工作空间,这更糟糕。我还考虑过调用子函数或 save
的选项。/load
,但没有得到任何结果,但也许我还没有足够认真地思考。
所以我想我需要将所有变量命名为 doctest__system__*
并忍受命名空间问题...除非您对避免变量名冲突的策略有其他想法?
最佳答案
这肯定是一个非常有趣的项目..我认为你拥有的最佳选择是编写一个单独的函数来执行测试,并为该函数内的所有变量使用唯一的前缀以避免名称冲突。这是我的尝试:
function [PREFIX_b varargout] = testContext(PREFIX_src, PREFIX_srcOutput)
%# TESTCONTEXT Executes the source code and tests for
%# equality against the expected output
%#
%# Input:
%# PREFIX_src - source to execute, cellarry of statements
%# PREFIX_srcOutput - output to expect, cellarray of output of each statement
%#
%# Output:
%# PREFIX_b - true/false for success/failure of test
%# note that the output is strtrim()'ed then strcmp()'ed
%# varargout{1} - variable names assigned in this confined context
%# varargout{2} - variable values assigned
%#
%# Example 1:
%# source = { 'I = 5+33;' 'I' };
%# output = { [], ['I =' char(10) ' 38'] };
%# b = testContext(source, output);
%#
%# Example 2:
%# source = { 'I = 5+33; J = 2;' 'K = 1;' 'disp(I+J+K)' };
%# output = { [], [], '41' };
%# [b varNames varValues] = testContext(source, output);
%#
%# See also: eval evalc
%#
PREFIX_b = true;
try
%# for each statement
for PREFIX_i=1:numel(PREFIX_src)
%# evaluate
PREFIX_output = evalc( PREFIX_src{PREFIX_i} );
PREFIX_output = strtrim(PREFIX_output); %# trim whitespaces
%# compare output
if ~isempty( PREFIX_srcOutput{PREFIX_i} )
if ~strcmp(PREFIX_output,PREFIX_srcOutput{PREFIX_i})
PREFIX_b = false;
return
end
end
end
if nargout > 1
%# list created variables in this context
%#clear ans
PREFIX_vars = whos('-regexp', '^(?!PREFIX_).*'); %# java regex negative lookahead
varargout{1} = { PREFIX_vars.name };
if nargout > 2
%# return those variables
varargout{2} = cell(1,numel(PREFIX_vars));
for PREFIX_i=1:numel(PREFIX_vars)
[~,varargout{2}{PREFIX_i}] = evalc( PREFIX_vars(PREFIX_i).name );
end
end
end
catch ME
warning(ME.identifier, ME.message)
PREFIX_b = false;
varargout{1} = {};
varargout{2} = {};
end
end
我假设您能够解析 m 文件以恢复要测试的示例,其中您拥有每个语句及其预期输出。
例如,考虑嵌入在函数 header 中的这个简单测试:
I = 5 + 33;
J = 2*I;
disp(I+J)
因为只有最后一条语句有输出,我们测试它为:
source = {'I = 5 + 33;' 'J = 2*I;' 'disp(I+J)'};
output = {[], [], '114'};
[b varNames varValues] = testContext(source, output)
结果:
b =
1
varNames =
'I' 'J'
varValues =
[38] [76]
它显示测试是通过还是失败。或者,该函数返回在该上下文中创建的变量列表及其值。
关于matlab - 在没有 namespace 污染的情况下运行 MATLAB 代码片段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3283586/